[#20190] Behavior: autoload calls rb_require() directly — Evan Phoenix <evan@...>

Hi everyone,

79 messages 2008/12/01
[#20200] Re: Behavior: autoload calls rb_require() directly — Yukihiro Matsumoto <matz@...> 2008/12/02

Hi,

[#20215] Re: Behavior: autoload calls rb_require() directly — Evan Phoenix <evan@...> 2008/12/02

[#20217] Re: Behavior: autoload calls rb_require() directly — Dave Thomas <dave@...> 2008/12/02

[#20301] Re: Behavior: autoload calls rb_require() directly — Yukihiro Matsumoto <matz@...> 2008/12/04

Hi,

[#20316] Re: Behavior: autoload calls rb_require() directly — Charles Oliver Nutter <charles.nutter@...> 2008/12/04

Yukihiro Matsumoto wrote:

[#20317] Re: Behavior: autoload calls rb_require() directly — Paul Brannan <pbrannan@...> 2008/12/04

On Fri, Dec 05, 2008 at 03:25:42AM +0900, Charles Oliver Nutter wrote:

[#20323] Leave my open classes alone (was Behavior: autoload calls rb_require() directly) — Dave Thomas <dave@...> 2008/12/04

[#20325] Re: Leave my open classes alone (was Behavior: autoload calls rb_require() directly) — Charles Oliver Nutter <charles.nutter@...> 2008/12/04

Dave Thomas wrote:

[#20328] Re: Leave my open classes alone (was Behavior: autoload calls rb_require() directly) — Yukihiro Matsumoto <matz@...> 2008/12/04

Hi,

[#20334] Re: Leave my open classes alone (was Behavior: autoload calls rb_require() directly) — Charles Oliver Nutter <charles.nutter@...> 2008/12/04

Yukihiro Matsumoto wrote:

[#20384] Re: Leave my open classes alone (was Behavior: autoload calls rb_require() directly) — Brent Roman <brent@...> 2008/12/05

[#20329] Re: Behavior: autoload calls rb_require() directly — daz <dooby@...10.karoo.co.uk> 2008/12/04

Charles Oliver Nutter wrote:

[#20335] Re: Behavior: autoload calls rb_require() directly — Charles Oliver Nutter <charles.nutter@...> 2008/12/04

daz wrote:

[#20341] Re: Behavior: autoload calls rb_require() directly — "Michael Selig" <michael.selig@...> 2008/12/04

On Fri, 05 Dec 2008 09:58:02 +1100, Charles Oliver Nutter

[#20344] Re: Behavior: autoload calls rb_require() directly — Charles Oliver Nutter <charles.nutter@...> 2008/12/05

Michael Selig wrote:

[#20214] Proposal: deferred blocks — "Yehuda Katz" <wycats@...>

Several people have played around with solutions that use ParseTree or

11 messages 2008/12/02

[#20235] autoload and concurrency — "Yehuda Katz" <wycats@...>

Merb uses autoload rather extensively. We have lately observed some

31 messages 2008/12/03
[#20236] Re: autoload and concurrency — Jim Deville <jdeville@...> 2008/12/03

This seems like a strong argument in favor of Ruby-core:20225.

[#20240] Re: autoload and concurrency — Charles Oliver Nutter <charles.nutter@...> 2008/12/03

Jim Deville wrote:

[#20242] Re: autoload and concurrency — Charles Oliver Nutter <charles.nutter@...> 2008/12/03

Charles Oliver Nutter wrote:

[#20245] Re: autoload and concurrency — "Yehuda Katz" <wycats@...> 2008/12/03

Also, this just illustrates that it's possible. In the case of Merb, we

[#20247] Re: autoload and concurrency — Tomas Matousek <Tomas.Matousek@...> 2008/12/03

I think it has already been concluded that autoload and require are inheren=

[#20241] [Bug #814] NoMethodError: undefined method `read_nonblock' for #<OpenSSL::SSL::SSLSocket:0x1a64f9a0> — Aaron Patterson <redmine@...>

Bug #814: NoMethodError: undefined method `read_nonblock' for #<OpenSSL::SSL::SSLSocket:0x1a64f9a0>

19 messages 2008/12/03
[#22538] [Bug #814] NoMethodError: undefined method `read_nonblock' for #<OpenSSL::SSL::SSLSocket:0x1a64f9a0> — Tony Arcieri <redmine@...> 2009/02/26

Issue #814 has been updated by Tony Arcieri.

[#20416] [Feature #839] Add code on each line of a backtrace output to the screen — Roger Pack <redmine@...>

Feature #839: Add code on each line of a backtrace output to the screen

12 messages 2008/12/08

[#20483] encoding of symbols — Dave Thomas <dave@...>

If I have a source file like this:

50 messages 2008/12/11
[#20494] Re: encoding of symbols — Yukihiro Matsumoto <matz@...> 2008/12/11

Hi,

[#20496] Re: encoding of symbols — Yukihiro Matsumoto <matz@...> 2008/12/12

Hi,

[#20522] Re: encoding of symbols — Charles Oliver Nutter <charles.nutter@...> 2008/12/13

Yukihiro Matsumoto wrote:

[#20526] Re: encoding of symbols — Brian Candler <B.Candler@...> 2008/12/13

On Sat, Dec 13, 2008 at 08:33:13PM +0900, Charles Oliver Nutter wrote:

[#20540] Re: 1.9 character encoding (was: encoding of symbols) — "Michael Selig" <michael.selig@...> 2008/12/14

On Sun, 14 Dec 2008 01:01:44 +1100, Brian Candler <B.Candler@pobox.com>

[#20545] Re: 1.9 character encoding (was: encoding of symbols) — "Michael Selig" <michael.selig@...> 2008/12/14

On Sun, 14 Dec 2008 11:57:55 +1100, Michael Selig

[#20562] Re: 1.9 character encoding (was: encoding of symbols) — Yukihiro Matsumoto <matz@...> 2008/12/15

Hi,

[#20619] Re: 1.9 character encoding (was: encoding of symbols) — danielcavanagh@... 2008/12/17

> You're right. When we have two strings with identical byte sequence

[#20502] [Bug #863] Openssl issues with fresh compile on Ubuntu — Brian Takita <redmine@...>

Bug #863: Openssl issues with fresh compile on Ubuntu

11 messages 2008/12/12

[#20557] [Bug #877] [win32] Ruby Standard Library (maybe smth else): Wrong Encoding in Files, Directories and Environment Variables — "Dmitry A. Ustalov" <redmine@...>

Bug #877: [win32] Ruby Standard Library (maybe smth else): Wrong Encoding in Files, Directories and Environment Variables

14 messages 2008/12/14

[#20564] [Bug #883] Failure: test_handle_special_CROSSREF_no_underscore(TestRDocMarkupToHtmlCrossref) — Kazuhiro NISHIYAMA <redmine@...>

Bug #883: Failure: test_handle_special_CROSSREF_no_underscore(TestRDocMarkupToHtmlCrossref)

9 messages 2008/12/15

[#20576] [Bug #888] zlib 1.2.3 does not work with Rubygems 1.3.1 (in Ruby 1.9.1) on Windows — Chauk-Mean PROUM <redmine@...>

Bug #888: zlib 1.2.3 does not work with Rubygems 1.3.1 (in Ruby 1.9.1) on Windows

14 messages 2008/12/15

[#20578] [Feature #889] erb.rb should use Array and << for eoutvar and not String and concat — Thomas Enebo <redmine@...>

Feature #889: erb.rb should use Array and << for eoutvar and not String and concat

15 messages 2008/12/15

[#20668] [Feature #905] Add String.new(fixnum) to preallocate large buffer — Charles Nutter <redmine@...>

Feature #905: Add String.new(fixnum) to preallocate large buffer

60 messages 2008/12/18
[#20671] Re: [Feature #905] Add String.new(fixnum) to preallocate large buffer — Yukihiro Matsumoto <matz@...> 2008/12/19

Hi

[#20674] Re: [Feature #905] Add String.new(fixnum) to preallocate large buffer — Charles Oliver Nutter <charles.nutter@...> 2008/12/19

Yukihiro Matsumoto wrote:

[#20697] Re: [Feature #905] Add String.new(fixnum) to preallocate large buffer — Jim Weirich <jim.weirich@...> 2008/12/19

[#20703] Re: [Feature #905] Add String.new(fixnum) to preallocate large buffer — Charles Oliver Nutter <charles.nutter@...> 2008/12/19

Jim Weirich wrote:

[#20704] Re: [Feature #905] Add String.new(fixnum) to preallocate large buffer — Dave Thomas <dave@...> 2008/12/19

[#28461] [Feature #905] Add String.new(fixnum) to preallocate large buffer — caleb clausen <redmine@...> 2010/03/04

Issue #905 has been updated by caleb clausen.

[#28491] [Feature #905] Add String.new(fixnum) to preallocate large buffer — Kurt Stephens <redmine@...> 2010/03/05

Issue #905 has been updated by Kurt Stephens.

[#20695] [Bug #907] Various system() and backticks problems on Windows — "James M. Lawrence" <redmine@...>

Bug #907: Various system() and backticks problems on Windows

13 messages 2008/12/19

[#20706] [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michael Selig <redmine@...>

Feature #908: Should be an easy way of reading N characters from am I/O stream

39 messages 2008/12/19
[#21816] [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michael Selig <redmine@...> 2009/02/03

Issue #908 has been updated by Michael Selig.

[#21825] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/04

In article <4988d2fa997f8_8527a9e32018e7@redmine.ruby-lang.org>,

[#21826] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — "Michael Selig" <michael.selig@...> 2009/02/04

Hi,

[#22100] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/14

In article <op.uotab6oa9245dp@kool>,

[#22125] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michal Suchanek <hramrach@...> 2009/02/15

2009/2/14 Tanaka Akira <akr@fsij.org>:

[#22146] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/15

In article <a5d587fb0902141711q780f0d24jef9be9b8bbe69b2a@mail.gmail.com>,

[#22182] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michal Suchanek <hramrach@...> 2009/02/16

2009/2/15 Tanaka Akira <akr@fsij.org>:

[#22213] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/18

In article <a5d587fb0902160252u56b50cfdv8e0fd36bb4f0b1b3@mail.gmail.com>,

[#22215] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michal Suchanek <hramrach@...> 2009/02/18

2009/2/18 Tanaka Akira <akr@fsij.org>:

[#22238] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — "Michael Selig" <michael.selig@...> 2009/02/18

On Thu, 19 Feb 2009 02:21:21 +1100, Michal Suchanek <hramrach@centrum.cz>

[#22253] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/19

In article <op.upklh9q19245dp@kool>,

[#22281] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Martin Duerst <duerst@...> 2009/02/20

At 19:00 09/02/19, Tanaka Akira wrote:

[#22332] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Tanaka Akira <akr@...> 2009/02/22

In article <6.0.0.20.2.20090220134502.0823ee98@localhost>,

[#22338] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — "Michael Selig" <michael.selig@...> 2009/02/22

On Mon, 23 Feb 2009 03:00:41 +1100, Tanaka Akira <akr@fsij.org> wrote:

[#22356] Re: [Feature #908] Should be an easy way of reading N characters from am I/O stream — Michal Suchanek <hramrach@...> 2009/02/23

2009/2/22 Michael Selig <michael.selig@fs.com.au>:

[#20723] [Bug #911] ArgumentError in Resolv#getaddress — Federico Builes <redmine@...>

Bug #911: ArgumentError in Resolv#getaddress

14 messages 2008/12/20

[#20797] [Bug #921] autoload is not thread-safe — Charles Nutter <redmine@...>

Bug #921: autoload is not thread-safe

15 messages 2008/12/22

[#20893] [Bug #932] incorrect case statement in "ext/dl/test/test_base.rb" causes library problems on openSUSE 11.1 64-bit — Ed Borasky <redmine@...>

Bug #932: incorrect case statement in "ext/dl/test/test_base.rb" causes library problems on openSUSE 11.1 64-bit

8 messages 2008/12/26

[#20978] Definable != is a Bad Thing™ — Ryan Davis <ryand-ruby@...>

> >> class X; def == o; :great; end; def != o; :horrible; end; end

20 messages 2008/12/30
[#20979] Re: Definable != is a Bad Thing™ — Yukihiro Matsumoto <matz@...> 2008/12/30

Hi,

[#20994] [Bug #956] Encoding: nl_langinfo(CODESET) on cygwin 1.5 always returns US-ASCII — Tom Link <redmine@...>

Bug #956: Encoding: nl_langinfo(CODESET) on cygwin 1.5 always returns US-ASCII

10 messages 2008/12/30

[#20999] Supporting Thread.critical=with native threads — Shri Borde <Shri.Borde@...>

Hi,

27 messages 2008/12/30
[#21002] Re: Supporting Thread.critical=with native threads — Eric Hodel <drbrain@...7.net> 2008/12/31

On Dec 30, 2008, at 15:00 PM, Shri Borde wrote:

[#21010] Re: Supporting Thread.critical=with native threads — Shri Borde <Shri.Borde@...> 2008/12/31

http://www.ruby-doc.org/core/classes/Thread.html#M000461 says:

[#21245] Re: Supporting Thread.critical=with native threads — Charles Oliver Nutter <charles.nutter@...> 2009/01/10

I'm starting come around to Shri's idea of critical= being represented

[#21353] Re: Supporting Thread.critical=with native threads — Shri Borde <Shri.Borde@...> 2009/01/14

SXMgb3BlbmluZyBhIGJ1ZyB0aGUgcmVjb21tZW5kZWQgd2F5IHRvIGdldCB0aGUgc3BlYyBjaGFu

[#21359] Re: Supporting Thread.critical=with native threads — Brent Roman <brent@...> 2009/01/15

[ruby-core:20497] Re: Status of copy-on-write friendly garbage collector

From: Yukihiro Matsumoto <matz@...>
Date: 2008-12-12 00:37:33 UTC
List: ruby-core #20497
Hi,

In message "Re: [ruby-core:20481] Re: Status of copy-on-write friendly garbage collector"
    on Fri, 12 Dec 2008 00:11:52 +0900, "Roger Pack" <rogerpack2005@gmail.com> writes:

|I assume that it works now, and was merged into trunk?

It works now, but have not yet been merged it since it still slows
down non-forking programs.  I attach the diff from trunk for those who
want to try and inspect the idea.

							matz.

Attachments (1)

o1_bitmap_marking.diff (18.8 KB, text/x-diff)
diff --git a/debug.c b/debug.c
index bfce7ad..384fbb2 100644
--- a/debug.c
+++ b/debug.c
@@ -31,7 +31,7 @@ static const union {
         RUBY_ENC_CODERANGE_7BIT    = ENC_CODERANGE_7BIT,
         RUBY_ENC_CODERANGE_VALID   = ENC_CODERANGE_VALID,
         RUBY_ENC_CODERANGE_BROKEN  = ENC_CODERANGE_BROKEN, 
-        RUBY_FL_MARK        = FL_MARK,
+        RUBY_FL_ALIGNOFF    = FL_ALIGNOFF,
         RUBY_FL_RESERVED    = FL_RESERVED,
         RUBY_FL_FINALIZE    = FL_FINALIZE,
         RUBY_FL_TAINT       = FL_TAINT,
diff --git a/gc.c b/gc.c
index d2ef85f..864143a 100644
--- a/gc.c
+++ b/gc.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <setjmp.h>
 #include <sys/types.h>
+#include <math.h>
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -248,6 +249,13 @@ typedef struct RVALUE {
 	    VALUE flags;		/* always 0 for freed obj */
 	    struct RVALUE *next;
 	} free;
+	struct {
+	    VALUE flags;
+	    struct RVALUE *next;
+	    int *map;
+	    VALUE slot;
+	    int limit;
+	} bitmap;
 	struct RBasic  basic;
 	struct RObject object;
 	struct RClass  klass;
@@ -279,6 +287,7 @@ struct heaps_slot {
     void *membase;
     RVALUE *slot;
     int limit;
+    RVALUE *bitmap;
 };
 
 #define HEAP_MIN_SLOTS 10000
@@ -308,6 +317,7 @@ typedef struct rb_objspace {
 	RVALUE *freelist;
 	RVALUE *range[2];
 	RVALUE *freed;
+	RVALUE *freed_bitmap;
     } heap;
     struct {
 	int dont_gc;
@@ -379,22 +389,12 @@ rb_objspace_alloc(void)
 #endif
 
 /* tiny heap size */
-/* 32KB */
-/*#define HEAP_SIZE 0x8000 */
-/* 128KB */
-/*#define HEAP_SIZE 0x20000 */
-/* 64KB */
-/*#define HEAP_SIZE 0x10000 */
-/* 16KB */
-#define HEAP_SIZE 0x4000
-/* 8KB */
-/*#define HEAP_SIZE 0x2000 */
-/* 4KB */
-/*#define HEAP_SIZE 0x1000 */
-/* 2KB */
-/*#define HEAP_SIZE 0x800 */
-
-#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
+#define BITMAP_ALIGN 0x4000
+
+/* (16KB/sizeof(RVALUE) + 2) * sizeof(RVALUE) */
+#define HEAP_SIZE 0x4024
+#define BITMAP_MASK  0xFFFFc000
+#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE) - 1)
 
 extern VALUE rb_cMutex;
 extern st_table *rb_class_tbl;
@@ -783,6 +783,149 @@ allocate_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
     heaps_length = next_heaps_length;
 }
 
+
+#define FIND_BITMAP(res, p) do {\
+    if (((RVALUE *)p)->as.free.flags & FL_ALIGNOFF) {\
+        res = (RVALUE *)((((VALUE)p & BITMAP_MASK) + BITMAP_ALIGN) / sizeof(RVALUE) * sizeof(RVALUE)); \
+    }\
+    else {\
+        res = (RVALUE *)(((VALUE)p & BITMAP_MASK) / sizeof(RVALUE) * sizeof(RVALUE));\
+    }\
+} while(0)
+
+#define NUM_IN_SLOT(p, slot) (((VALUE)p - (VALUE)slot)/sizeof(RVALUE))
+#define BITMAP_INDEX(bmap, p) (NUM_IN_SLOT(p, bmap->as.bitmap.slot) / (sizeof(int) * 8))
+// #define BITMAP_INDEX(bmap, p) (NUM_IN_SLOT(p, bmap->as.bitmap.slot) >> 5)
+#define BITMAP_OFFSET(bmap, p) (NUM_IN_SLOT(p, bmap->as.bitmap.slot) & ((sizeof(int) * 8)-1))
+#define MARKED_IN_BITMAP(bmap, p) (bmap->as.bitmap.map[BITMAP_INDEX(bmap, p)] & 1 << BITMAP_OFFSET(bmap, p))
+#define MARK_IN_BITMAP(bmap, p) (bmap->as.bitmap.map[BITMAP_INDEX(bmap, p)] |= 1 << BITMAP_OFFSET(bmap, p))
+#define CLEAR_IN_BITMAP(bmap, p) (bmap->as.bitmap.map[BITMAP_INDEX(bmap, p)] &= ~(1 << BITMAP_OFFSET(bmap, p)))
+#define MARKED_IN_BITMAP_DIRECT(map, index, offset) (map[index] & 1 << offset)
+#define MARK_IN_BITMAP_DIRECT(map, index, offset) (map[index] |= 1 << offset)
+
+//for debug
+void
+bitmap_p(RVALUE *p)
+{
+    RVALUE *bmap;
+    int index, offset, marked;
+
+    FIND_BITMAP(bmap, p);
+    index = BITMAP_INDEX(bmap, p);
+    offset = BITMAP_OFFSET(bmap, p);
+    marked = MARKED_IN_BITMAP(bmap, p);
+    printf("bitmap : ((RVALUE *)%p)\n", bmap);
+    printf("map_index : %d | offset : %d\n", index, offset);
+    printf("is mark ? %s\n", marked? "true" : "false");
+}
+
+VALUE
+find_bitmap(RVALUE *p) {
+    RVALUE *res;
+
+    FIND_BITMAP(res, p);
+    return (VALUE)res;
+}
+
+void
+dump_bitmap(RVALUE *bmap) {
+    int i;
+    
+    for (i = 0; i < 26; i++) {
+	printf("dump %p map %d : %d %s\n", bmap, i, bmap->as.bitmap.map[i], bmap->as.bitmap.map[i]? "remain" : "clean");
+    }
+}
+
+void
+bitmap2obj(RVALUE *bmap, int index, int offset)
+{
+    printf("(RVALUE *)%p\n", (RVALUE *)(bmap->as.bitmap.slot + (index * sizeof(int) * 8 + offset) * sizeof(RVALUE)));
+}
+
+
+static void
+make_bitmap(struct heaps_slot *slot)
+{
+    RVALUE *p, *pend, *bitmap, *last, *border;
+    int *map = 0;
+    int size;
+   
+    p = slot->slot;
+    pend = p + slot->limit;
+    last = pend - 1;
+    RBASIC(last)->flags = 0;
+    FIND_BITMAP(bitmap, last);
+    if (bitmap < p || pend <= bitmap) {
+	rb_bug("not include in heap slot: result bitmap(%p), find (%p), p (%p), pend(%p)", bitmap, last, p, pend);
+    }
+    border = bitmap;
+    if (!((VALUE)border % BITMAP_ALIGN)) {
+	border--;
+    }
+    while (p < pend) {
+	if (p <= border) {
+	    RBASIC(p)->flags = FL_ALIGNOFF;
+	}
+	else {
+	    RBASIC(p)->flags = 0;
+	}
+	p++;
+    }
+
+    size = sizeof(int) * (HEAP_OBJ_LIMIT / (sizeof(int) * 8)+1);
+    map = (int *)malloc(size);
+    if (map == 0) {
+	rb_memerror();
+    }
+    MEMZERO(map, int, (size/sizeof(int)));
+    bitmap->as.bitmap.flags |= T_BITMAP;
+    bitmap->as.bitmap.map = map;
+    bitmap->as.bitmap.slot = (VALUE)slot->slot;
+    bitmap->as.bitmap.limit = slot->limit;
+    slot->bitmap = bitmap;
+}
+
+void
+test_bitmap(RVALUE *p, RVALUE *pend)
+{
+    RVALUE *first, *bmap = 0, *bmap_tmp;
+    int i;
+
+    first = p;
+    FIND_BITMAP(bmap_tmp, p);
+    while (p < pend) {
+	if (MARKED_IN_BITMAP(bmap, p)) printf("already marking! %p\n", p);
+	if (bmap_tmp != p) {
+	    FIND_BITMAP(bmap, p);
+	    if (bmap_tmp != bmap) printf("diffrence bmap %p : %p\n", bmap_tmp, bmap);
+	    MARK_IN_BITMAP(bmap, p);
+	}
+	else {
+	    MARK_IN_BITMAP(bmap, p);
+	}
+	if (!MARKED_IN_BITMAP(bmap, p)) printf("not marking! %p\n", p);
+	p++;
+    }
+    for (i =0; i < 26; i++) {
+	printf("bitmap[%d] : %x\n", i, bmap->as.bitmap.map[i]);
+    }
+    p = first;
+    while (p < pend) {
+	if (bmap_tmp != p) {
+	    FIND_BITMAP(bmap, p);
+	    CLEAR_IN_BITMAP(bmap, p);
+	}
+	else {
+	    CLEAR_IN_BITMAP(bmap, p);
+	}
+	if (MARKED_IN_BITMAP(bmap, p)) printf("not clear! %p\n", p);
+	p++;
+    }
+    for (i =0; i < 26; i++) {
+	printf("bitmap[%d] : %x\n", i, bmap->as.bitmap.map[i]);
+    }
+}
+
 static void
 assign_heap_slot(rb_objspace_t *objspace)
 {
@@ -801,9 +944,6 @@ assign_heap_slot(rb_objspace_t *objspace)
     membase = p;
     if ((VALUE)p % sizeof(RVALUE) != 0) {
 	p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
-	if ((HEAP_SIZE - HEAP_OBJ_LIMIT * sizeof(RVALUE)) < ((char*)p - (char*)membase)) {
-	    objs--;
-	}
     }
 
     lo = 0;
@@ -825,6 +965,7 @@ assign_heap_slot(rb_objspace_t *objspace)
     if (hi < heaps_used) {
 	MEMMOVE(&heaps[hi+1], &heaps[hi], struct heaps_slot, heaps_used - hi);
     }
+
     heaps[hi].membase = membase;
     heaps[hi].slot = p;
     heaps[hi].limit = objs;
@@ -833,10 +974,12 @@ assign_heap_slot(rb_objspace_t *objspace)
     if (himem < pend) himem = pend;
     heaps_used++;
 
+    make_bitmap(&heaps[hi]);
     while (p < pend) {
-	p->as.free.flags = 0;
-	p->as.free.next = freelist;
-	freelist = p;
+	if (BUILTIN_TYPE(p) != T_BITMAP) {
+	    p->as.free.next = freelist;
+	    freelist = p;
+	}
 	p++;
     }
 }
@@ -888,6 +1031,7 @@ static VALUE
 rb_newobj_from_heap(rb_objspace_t *objspace)
 {
     VALUE obj;
+    int bmap_left = 0;
 	
     if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) {
     	if (!heaps_increment(objspace) && !garbage_collect(objspace)) {
@@ -899,7 +1043,13 @@ rb_newobj_from_heap(rb_objspace_t *objspace)
     obj = (VALUE)freelist;
     freelist = freelist->as.free.next;
 
+    if (RANY(obj)->as.free.flags & FL_ALIGNOFF) {
+	bmap_left = Qtrue;
+    }
     MEMZERO((void*)obj, RVALUE, 1);
+    if (bmap_left) {
+	RANY(obj)->as.free.flags = FL_ALIGNOFF;
+    }
 #ifdef GC_DEBUG
     RANY(obj)->file = rb_sourcefile();
     RANY(obj)->line = rb_sourceline();
@@ -915,13 +1065,15 @@ rb_fill_value_cache(rb_thread_t *th)
     rb_objspace_t *objspace = &rb_objspace;
     int i;
     VALUE rv;
+    RVALUE *bmap;
 
     /* LOCK */
     for (i=0; i<RUBY_VM_VALUE_CACHE_SIZE; i++) {
 	VALUE v = rb_newobj_from_heap(objspace);
 
 	th->value_cache[i] = v;
-	RBASIC(v)->flags = FL_MARK;
+	FIND_BITMAP(bmap, v);
+	MARK_IN_BITMAP(bmap, v);
     }
     th->value_cache_ptr = &th->value_cache[0];
     rv = rb_newobj_from_heap(objspace);
@@ -960,7 +1112,7 @@ rb_newobj(void)
 
 #if USE_VALUE_CACHE
     if (v) {
-	RBASIC(v)->flags = 0;
+	FL_FORCE_SET(p, 0);
 	th->value_cache_ptr++;
     }
     else {
@@ -1085,18 +1237,21 @@ init_mark_stack(rb_objspace_t *objspace)
 static void gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev);
 static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev);
 
+#define IS_FREE_CELL(obj) ((obj->as.basic.flags & ~(FL_ALIGNOFF)) == 0)
+
 static void
 gc_mark_all(rb_objspace_t *objspace)
 {
-    RVALUE *p, *pend;
+    RVALUE *p, *pend, *bmap;
     size_t i;
 
     init_mark_stack(objspace);
     for (i = 0; i < heaps_used; i++) {
 	p = heaps[i].slot; pend = p + heaps[i].limit;
+	bmap = heaps[i].bitmap;
 	while (p < pend) {
-	    if ((p->as.basic.flags & FL_MARK) &&
-		(p->as.basic.flags != FL_MARK)) {
+	    if (MARKED_IN_BITMAP(bmap, p) &&
+		!(IS_FREE_CELL(p))) {
 		gc_mark_children(objspace, (VALUE)p, 0);
 	    }
 	    p++;
@@ -1271,13 +1426,15 @@ rb_gc_mark_maybe(VALUE obj)
 static void
 gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev)
 {
-    register RVALUE *obj;
+    register RVALUE *obj, *bmap;
 
     obj = RANY(ptr);
     if (rb_special_const_p(ptr)) return; /* special const not marked */
-    if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
+    if (IS_FREE_CELL(obj)) return;       /* free cell */
+    if (BUILTIN_TYPE(obj) == T_BITMAP) return;
+    FIND_BITMAP(bmap, obj);
+    if (MARKED_IN_BITMAP(bmap, obj)) return;  /* already marked */
+    MARK_IN_BITMAP(bmap, obj);
 
     if (lev > GC_LEVEL_MAX || (lev == 0 && stack_check())) {
 	if (!mark_stack_overflow) {
@@ -1303,16 +1460,17 @@ rb_gc_mark(VALUE ptr)
 static void
 gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
 {
-    register RVALUE *obj = RANY(ptr);
+    register RVALUE *obj = RANY(ptr), *bmap;
 
     goto marking;		/* skip */
 
   again:
     obj = RANY(ptr);
     if (rb_special_const_p(ptr)) return; /* special const not marked */
-    if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
+    if (IS_FREE_CELL(obj)) return;       /* free cell */
+    FIND_BITMAP(bmap, obj);
+    if (MARKED_IN_BITMAP(bmap, obj)) return;  /* already marked */
+    MARK_IN_BITMAP(bmap, obj);
 
   marking:
     if (FL_TEST(obj, FL_EXIVAR)) {
@@ -1573,8 +1731,12 @@ static int obj_free(rb_objspace_t *, VALUE);
 static inline void
 add_freelist(rb_objspace_t *objspace, RVALUE *p)
 {
+    RVALUE *bmap;
+
     VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-    p->as.free.flags = 0;
+    FL_FORCE_SET(p, 0);
+    FIND_BITMAP(bmap, p);
+    CLEAR_IN_BITMAP(bmap, p);
     p->as.free.next = freelist;
     freelist = p;
 }
@@ -1600,15 +1762,17 @@ static void
 free_unused_heaps(rb_objspace_t *objspace)
 {
     size_t i, j;
-    RVALUE *last = 0;
+    RVALUE *last = 0, *bmap = 0;
 
     for (i = j = 1; j < heaps_used; i++) {
 	if (heaps[i].limit == 0) {
 	    if (!last) {
 		last = heaps[i].membase;
+		bmap = heaps[i].bitmap;
 	    }
 	    else {
 		free(heaps[i].membase);
+		free(heaps[i].bitmap->as.bitmap.map);
 	    }
 	    heaps_used--;
 	}
@@ -1622,10 +1786,13 @@ free_unused_heaps(rb_objspace_t *objspace)
     if (last) {
 	if (last < heaps_freed) {
 	    free(heaps_freed);
+	    free(objspace->heap.freed_bitmap->as.bitmap.map);
 	    heaps_freed = last;
+	    heaps_freed = bmap;
 	}
 	else {
 	    free(last);
+	    free(bmap->as.bitmap.map);
 	}
     }
 }
@@ -1653,25 +1820,35 @@ gc_sweep(rb_objspace_t *objspace)
 	int free_num = 0, final_num = 0;
 	RVALUE *free = freelist;
 	RVALUE *final = final_list;
-	int deferred;
+	int *map = heaps[i].bitmap->as.bitmap.map;
+	int deferred, bmap_index = 0, bmap_offset = 0;
 
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
-	    if (!(p->as.basic.flags & FL_MARK)) {
-		if (p->as.basic.flags &&
+	    if (BUILTIN_TYPE(p) == T_BITMAP) {
+		free_num++;
+	    }
+	    else if(!(MARKED_IN_BITMAP_DIRECT(map, bmap_index, bmap_offset))) {
+		if (!(IS_FREE_CELL(p)) &&
 		    ((deferred = obj_free(objspace, (VALUE)p)) ||
 		     ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) {
 		    if (!deferred) {
-			p->as.free.flags = T_ZOMBIE;
+			FL_FORCE_SET(p, T_ZOMBIE);
 			RDATA(p)->dfree = 0;
 		    }
-		    p->as.free.flags |= FL_MARK;
 		    p->as.free.next = final_list;
 		    final_list = p;
 		    final_num++;
 		}
 		else {
-		    add_freelist(objspace, p);
+		    /* Do not touch the fields if they don't have to be modified.
+		     * This is in order to preserve copy-on-write semantics.
+		     */
+		    if (!IS_FREE_CELL(p))
+			FL_FORCE_SET(p, 0);
+		    if (p->as.free.next != freelist)
+			p->as.free.next = freelist;
+		    freelist = p;
 		    free_num++;
 		}
 	    }
@@ -1680,11 +1857,16 @@ gc_sweep(rb_objspace_t *objspace)
 		/* do nothing remain marked */
 	    }
 	    else {
-		RBASIC(p)->flags &= ~FL_MARK;
 		live++;
 	    }
 	    p++;
+	    bmap_offset++;
+	    if (bmap_offset >= (sizeof(int) * 8)) {
+		bmap_index++;
+		bmap_offset = 0;
+	    }
 	}
+	MEMZERO(heaps[i].bitmap->as.bitmap.map, int, bmap_index+1);
 	if (final_num + free_num == heaps[i].limit && freed > do_heap_free) {
 	    RVALUE *pp;
 
@@ -1714,11 +1896,16 @@ gc_sweep(rb_objspace_t *objspace)
 
     /* clear finalization list */
     if (final_list) {
+	RVALUE *bmap, *pp;
+	for (pp = final_list; pp != 0; pp = pp->as.free.next) {
+	    FIND_BITMAP(bmap, pp);
+	    MARK_IN_BITMAP(bmap, pp);
+	}
 	GC_PROF_SET_HEAP_INFO;
 	deferred_final_list = final_list;
 	RUBY_VM_SET_FINALIZER_INTERRUPT(GET_THREAD());
     }
-    else{
+    else {
 	free_unused_heaps(objspace);
 	GC_PROF_SET_HEAP_INFO;
     }
@@ -1734,7 +1921,7 @@ rb_gc_force_recycle(VALUE p)
 static inline void
 make_deferred(RVALUE *p)
 {
-    p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_ZOMBIE;
+    FL_FORCE_SET(p, ((p->as.basic.flags & ~T_MASK) | T_ZOMBIE));
 }
 
 static inline void
@@ -2102,12 +2289,13 @@ os_obj_of(rb_objspace_t *objspace, VALUE of)
 
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	for (;p < pend; p++) {
-	    if (p->as.basic.flags) {
+	    if (!IS_FREE_CELL(p)) {
 		switch (BUILTIN_TYPE(p)) {
 		  case T_NONE:
 		  case T_ICLASS:
 		  case T_NODE:
 		  case T_ZOMBIE:
+		  case T_BITMAP:
 		    continue;
 		  case T_CLASS:
 		    if (FL_TEST(p, FL_SINGLETON)) continue;
@@ -2311,10 +2499,12 @@ rb_gc_finalize_deferred(void)
 static int
 chain_finalized_object(st_data_t key, st_data_t val, st_data_t arg)
 {
-    RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg;
+    RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg, *bmap;
     if (p->as.basic.flags & FL_FINALIZE) {
 	if (BUILTIN_TYPE(p) != T_ZOMBIE) {
-	    p->as.free.flags = FL_MARK | T_ZOMBIE; /* remain marked */
+	    FL_FORCE_SET(p, T_ZOMBIE);
+	    FIND_BITMAP(bmap, p);
+	    MARK_IN_BITMAP(bmap, p);
 	    RDATA(p)->dfree = 0;
 	}
 	p->as.free.next = *final_list;
@@ -2358,7 +2548,7 @@ rb_gc_call_finalizer_at_exit(void)
 	    if (BUILTIN_TYPE(p) == T_DATA &&
 		DATA_PTR(p) && RANY(p)->as.data.dfree &&
 		RANY(p)->as.basic.klass != rb_cThread && RANY(p)->as.basic.klass != rb_cMutex) {
-		p->as.free.flags = 0;
+		FL_FORCE_SET(p, 0);
 		if ((long)RANY(p)->as.data.dfree == -1) {
 		    xfree(DATA_PTR(p));
 		}
@@ -2372,6 +2562,7 @@ rb_gc_call_finalizer_at_exit(void)
 		if (RANY(p)->as.file.fptr) {
 		    make_io_deferred(RANY(p));
 		    RANY(p)->as.free.next = final_list;
+		    FL_FORCE_SET(p, 0);
 		    final_list = p;
 		}
 	    }
@@ -2564,7 +2755,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
 
         p = heaps[i].slot; pend = p + heaps[i].limit;
         for (;p < pend; p++) {
-            if (p->as.basic.flags) {
+	    if (!IS_FREE_CELL(p)) {
                 counts[BUILTIN_TYPE(p)]++;
             }
             else {
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index b1fe650..40eca5f 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -310,6 +310,7 @@ enum ruby_value_type {
     RUBY_T_FALSE  = 0x13,
     RUBY_T_SYMBOL = 0x14,
     RUBY_T_FIXNUM = 0x15,
+    RUBY_T_BITMAP = 0x19,
 
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
@@ -334,6 +335,7 @@ enum ruby_value_type {
 #define T_BIGNUM RUBY_T_BIGNUM
 #define T_FILE   RUBY_T_FILE
 #define T_FIXNUM RUBY_T_FIXNUM
+#define T_BITMAP RUBY_T_BITMAP
 #define T_TRUE   RUBY_T_TRUE
 #define T_FALSE  RUBY_T_FALSE
 #define T_DATA   RUBY_T_DATA
@@ -499,9 +501,17 @@ char *rb_str2cstr(VALUE,long*);
 #define CHR2FIX(x) INT2FIX((long)((x)&0xff))
 
 VALUE rb_newobj(void);
+#define FL_FORCE_SET(obj,t) do {\
+    if (RBASIC(obj)->flags & FL_ALIGNOFF) {\
+	RBASIC(obj)->flags = FL_ALIGNOFF | t;\
+    }\
+    else {\
+	RBASIC(obj)->flags = t;\
+    }\
+} while(0)
 #define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
 #define OBJSETUP(obj,c,t) do {\
-    RBASIC(obj)->flags = (t);\
+    FL_FORCE_SET(obj, t);\
     RBASIC(obj)->klass = (c);\
     if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT | FL_UNTRUSTED);\
 } while (0)
@@ -777,7 +787,7 @@ struct RBignum {
 #define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
 
 #define FL_SINGLETON FL_USER0
-#define FL_MARK      (((VALUE)1)<<5)
+#define FL_ALIGNOFF  (((VALUE)1)<<5)
 #define FL_RESERVED  (((VALUE)1)<<6) /* will be used in the future GC */
 #define FL_FINALIZE  (((VALUE)1)<<7)
 #define FL_TAINT     (((VALUE)1)<<8)
diff --git a/object.c b/object.c
index be99de6..7cc9f32 100644
--- a/object.c
+++ b/object.c
@@ -233,7 +233,8 @@ rb_obj_clone(VALUE obj)
     }
     clone = rb_obj_alloc(rb_obj_class(obj));
     RBASIC(clone)->klass = rb_singleton_class_clone(obj);
-    RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE);
+    RBASIC(clone)->flags = ((RBASIC(obj)->flags & ~(FL_ALIGNOFF|FL_FREEZE|FL_FINALIZE)) |
+			    FL_TEST(clone, FL_ALIGNOFF|FL_TAINT|FL_UNTRUSTED));
     init_copy(clone, obj);
     RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
 
diff --git a/vm.c b/vm.c
index 782fc99..11d0ebe 100644
--- a/vm.c
+++ b/vm.c
@@ -1479,7 +1479,7 @@ thread_free(void *ptr)
 	    VALUE *ptr = th->value_cache_ptr;
 	    while (*ptr) {
 		VALUE v = *ptr;
-		RBASIC(v)->flags = 0;
+		FL_FORCE_SET(v, 0);
 		RBASIC(v)->klass = 0;
 		ptr++;
 	    }
@@ -1789,7 +1789,7 @@ Init_VM(void)
 
     /* ::VM::FrozenCore */
     fcore = rb_class_new(rb_cBasicObject);
-    RBASIC(fcore)->flags = T_ICLASS;
+    FL_FORCE_SET(fcore, T_ICLASS);
     klass = rb_singleton_class(fcore);
     rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
     rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);

In This Thread

Prev Next