--Multipart_Fri_Dec_12_09:44:29_2008-1
Content-Type: text/plain; charset=US-ASCII
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.
--Multipart_Fri_Dec_12_09:44:29_2008-1
Content-Type: application/octet-stream; type=patch
Content-Disposition: attachment; filename="o1_bitmap_marking.diff"
Content-Transfer-Encoding: 7bit
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 NC_CODERANGE_7BIT,
RUBY_ENC_CODERANGE_VALID NC_CODERANGE_VALID,
RUBY_ENC_CODERANGE_BROKEN NC_CODERANGE_BROKEN,
- RUBY_FL_MARK L_MARK,
+ RUBY_FL_ALIGNOFF L_ALIGNOFF,
RUBY_FL_RESERVED L_RESERVED,
RUBY_FL_FINALIZE L_FINALIZE,
RUBY_FL_TAINT L_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 ext_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)] | << 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] | << offset)
+
+//for debug
+void
+bitmap_p(RVALUE *p)
+{
+ RVALUE *bmap;
+ int index, offset, marked;
+
+ FIND_BITMAP(bmap, p);
+ index ITMAP_INDEX(bmap, p);
+ offset ITMAP_OFFSET(bmap, p);
+ marked ARKED_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 ; 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 ;
+ int size;
+
+ p lot->slot;
+ pend + slot->limit;
+ last end - 1;
+ RBASIC(last)->flags ;
+ FIND_BITMAP(bitmap, last);
+ if (bitmap < p || pend < itmap) {
+ rb_bug("not include in heap slot: result bitmap(%p), find (%p), p (%p), pend(%p)", bitmap, last, p, pend);
+ }
+ border itmap;
+ if (!((VALUE)border % BITMAP_ALIGN)) {
+ border--;
+ }
+ while (p < pend) {
+ if (p < order) {
+ RBASIC(p)->flags L_ALIGNOFF;
+ }
+ else {
+ RBASIC(p)->flags ;
+ }
+ p++;
+ }
+
+ size izeof(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 | _BITMAP;
+ bitmap->as.bitmap.map ap;
+ bitmap->as.bitmap.slot VALUE)slot->slot;
+ bitmap->as.bitmap.limit lot->limit;
+ slot->bitmap itmap;
+}
+
+void
+test_bitmap(RVALUE *p, RVALUE *pend)
+{
+ RVALUE *first, *bmap , *bmap_tmp;
+ int i;
+
+ first ;
+ FIND_BITMAP(bmap_tmp, p);
+ while (p < pend) {
+ if (MARKED_IN_BITMAP(bmap, p)) printf("already marking! %p\n", p);
+ if (bmap_tmp ! ) {
+ FIND_BITMAP(bmap, p);
+ if (bmap_tmp ! map) 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 i < 26; i++) {
+ printf("bitmap[%d] : %x\n", i, bmap->as.bitmap.map[i]);
+ }
+ p irst;
+ while (p < pend) {
+ if (bmap_tmp ! ) {
+ 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 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 ;
if ((VALUE)p % sizeof(RVALUE) ! ) {
p RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
- if ((HEAP_SIZE - HEAP_OBJ_LIMIT * sizeof(RVALUE)) < ((char*)p - (char*)membase)) {
- objs--;
- }
}
lo ;
@@ -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 embase;
heaps[hi].slot ;
heaps[hi].limit bjs;
@@ -833,10 +974,12 @@ assign_heap_slot(rb_objspace_t *objspace)
if (himem < pend) himem end;
heaps_used++;
+ make_bitmap(&heaps[hi]);
while (p < pend) {
- p->as.free.flags ;
- p->as.free.next reelist;
- freelist ;
+ if (BUILTIN_TYPE(p) ! _BITMAP) {
+ p->as.free.next reelist;
+ freelist ;
+ }
p++;
}
}
@@ -888,6 +1031,7 @@ static VALUE
rb_newobj_from_heap(rb_objspace_t *objspace)
{
VALUE obj;
+ int bmap_left ;
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 reelist->as.free.next;
+ if (RANY(obj)->as.free.flags & FL_ALIGNOFF) {
+ bmap_left true;
+ }
MEMZERO((void*)obj, RVALUE, 1);
+ if (bmap_left) {
+ RANY(obj)->as.free.flags L_ALIGNOFF;
+ }
#ifdef GC_DEBUG
RANY(obj)->file b_sourcefile();
RANY(obj)->line b_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 i<RUBY_VM_VALUE_CACHE_SIZE; i++) {
VALUE v b_newobj_from_heap(objspace);
th->value_cache[i] ;
- RBASIC(v)->flags L_MARK;
+ FIND_BITMAP(bmap, v);
+ MARK_IN_BITMAP(bmap, v);
}
th->value_cache_ptr th->value_cache[0];
rv b_newobj_from_heap(objspace);
@@ -960,7 +1112,7 @@ rb_newobj(void)
#if USE_VALUE_CACHE
if (v) {
- RBASIC(v)->flags ;
+ 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 ; i < heaps_used; i++) {
p eaps[i].slot; pend + heaps[i].limit;
+ bmap eaps[i].bitmap;
while (p < pend) {
- if ((p->as.basic.flags & FL_MARK) &&
- (p->as.basic.flags ! L_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 ANY(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 | L_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 ANY(ptr);
+ register RVALUE *obj ANY(ptr), *bmap;
goto marking; /* skip */
again:
obj ANY(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 | L_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 ;
+ FL_FORCE_SET(p, 0);
+ FIND_BITMAP(bmap, p);
+ CLEAR_IN_BITMAP(bmap, p);
p->as.free.next reelist;
freelist ;
}
@@ -1600,15 +1762,17 @@ static void
free_unused_heaps(rb_objspace_t *objspace)
{
size_t i, j;
- RVALUE *last ;
+ RVALUE *last , *bmap ;
for (i ; j < heaps_used; i++) {
if (heaps[i].limit 0) {
if (!last) {
last eaps[i].membase;
+ bmap eaps[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 ast;
+ heaps_freed map;
}
else {
free(last);
+ free(bmap->as.bitmap.map);
}
}
}
@@ -1653,25 +1820,35 @@ gc_sweep(rb_objspace_t *objspace)
int free_num , final_num ;
RVALUE *free reelist;
RVALUE *final inal_list;
- int deferred;
+ int *map eaps[i].bitmap->as.bitmap.map;
+ int deferred, bmap_index , bmap_offset ;
p eaps[i].slot; pend + 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 bj_free(objspace, (VALUE)p)) ||
((FL_TEST(p, FL_FINALIZE)) && need_call_final))) {
if (!deferred) {
- p->as.free.flags _ZOMBIE;
+ FL_FORCE_SET(p, T_ZOMBIE);
RDATA(p)->dfree ;
}
- p->as.free.flags | L_MARK;
p->as.free.next inal_list;
final_list ;
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 ! reelist)
+ p->as.free.next reelist;
+ freelist ;
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 ;
+ }
}
+ 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 inal_list; pp ! ; pp p->as.free.next) {
+ FIND_BITMAP(bmap, pp);
+ MARK_IN_BITMAP(bmap, pp);
+ }
GC_PROF_SET_HEAP_INFO;
deferred_final_list inal_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 eaps[i].slot; pend + 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) ! _ZOMBIE) {
- p->as.free.flags L_MARK | T_ZOMBIE; /* remain marked */
+ FL_FORCE_SET(p, T_ZOMBIE);
+ FIND_BITMAP(bmap, p);
+ MARK_IN_BITMAP(bmap, p);
RDATA(p)->dfree ;
}
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 ! b_cThread && RANY(p)->as.basic.klass ! b_cMutex) {
- p->as.free.flags ;
+ 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 inal_list;
+ FL_FORCE_SET(p, 0);
final_list ;
}
}
@@ -2564,7 +2755,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
p eaps[i].slot; pend + 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 x13,
RUBY_T_SYMBOL x14,
RUBY_T_FIXNUM x15,
+ RUBY_T_BITMAP x19,
RUBY_T_UNDEF x1b,
RUBY_T_NODE x1c,
@@ -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 L_ALIGNOFF | t;\
+ }\
+ else {\
+ RBASIC(obj)->flags ;\
+ }\
+} 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() > ) 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 b_obj_alloc(rb_obj_class(obj));
RBASIC(clone)->klass b_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 | BASIC(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 h->value_cache_ptr;
while (*ptr) {
VALUE v ptr;
- RBASIC(v)->flags ;
+ FL_FORCE_SET(v, 0);
RBASIC(v)->klass ;
ptr++;
}
@@ -1789,7 +1789,7 @@ Init_VM(void)
/* ::VM::FrozenCore */
fcore b_class_new(rb_cBasicObject);
- RBASIC(fcore)->flags _ICLASS;
+ FL_FORCE_SET(fcore, T_ICLASS);
klass b_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);
--Multipart_Fri_Dec_12_09:44:29_2008-1--