ruby-changes:67221
From: Peter <ko1@a...>
Date: Mon, 23 Aug 2021 23:55:14 +0900 (JST)
Subject: [ruby-changes:67221] eddd369e73 (master): Revert "[Feature #18045] Implement size classes for GC"
https://git.ruby-lang.org/ruby.git/commit/?id=eddd369e73 From eddd369e7378ec762cf81a226aec1a2b8719bf7a Mon Sep 17 00:00:00 2001 From: Peter Zhu <peter@p...> Date: Mon, 23 Aug 2021 10:49:14 -0400 Subject: Revert "[Feature #18045] Implement size classes for GC" This reverts commits 48ff7a9f3e47bffb3e4d067a12ba9b936261caa0 and b2e2cf2dedd104acad8610721db5e4d341f135ef because it is causing crashes in SPARC solaris and i386 debian. --- class.c | 3 +- ext/objspace/objspace.c | 2 + gc.c | 1428 +++++++++++++++++------------------- include/ruby/internal/value_type.h | 2 + internal/gc.h | 6 +- misc/lldb_cruby.py | 10 +- vm_eval.c | 1 + 7 files changed, 692 insertions(+), 760 deletions(-) diff --git a/class.c b/class.c index 4c469ff..5fa51df 100644 --- a/class.c +++ b/class.c @@ -185,7 +185,8 @@ class_alloc(VALUE flags, VALUE klass) https://github.com/ruby/ruby/blob/trunk/class.c#L185 RVARGC_NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | FL_PROMOTED1 /* start from age == 2 */ | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0), payload_size); #if USE_RVARGC - obj->ptr = (rb_classext_t *)rb_gc_rvargc_object_data((VALUE)obj); + obj->ptr = (rb_classext_t *)rb_rvargc_payload_data_ptr((VALUE)obj + rb_slot_size()); + RB_OBJ_WRITTEN(obj, Qundef, (VALUE)obj + rb_slot_size()); #else obj->ptr = ZALLOC(rb_classext_t); #endif diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index 3fa4fd2..72d1eb8 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -66,6 +66,7 @@ total_i(VALUE v, void *ptr) https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L66 case T_IMEMO: case T_ICLASS: case T_NODE: + case T_PAYLOAD: case T_ZOMBIE: return; default: @@ -224,6 +225,7 @@ type2sym(enum ruby_value_type i) https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L225 CASE_TYPE(T_ICLASS); CASE_TYPE(T_MOVED); CASE_TYPE(T_ZOMBIE); + CASE_TYPE(T_PAYLOAD); #undef CASE_TYPE default: rb_bug("type2sym: unknown type (%d)", i); } diff --git a/gc.c b/gc.c index 4c28c68..fa4ab44 100644 --- a/gc.c +++ b/gc.c @@ -556,6 +556,7 @@ typedef struct gc_profile_record { https://github.com/ruby/ruby/blob/trunk/gc.c#L556 } gc_profile_record; #define FL_FROM_FREELIST FL_USER0 +#define FL_FROM_PAYLOAD FL_USER0 struct RMoved { VALUE flags; @@ -569,12 +570,31 @@ struct RMoved { https://github.com/ruby/ruby/blob/trunk/gc.c#L570 #pragma pack(push, 4) /* == SIZEOF_VALUE: magic for reducing sizeof(RVALUE): 24 -> 20 */ #endif +struct RPayload { + VALUE flags; +}; +#define RPAYLOAD(obj) ((struct RPayload *)obj) +static unsigned short +RPAYLOAD_LEN(VALUE obj) +{ + unsigned short len = (unsigned short)(RPAYLOAD(obj)->flags >> FL_USHIFT); + return len; +} + +static void +RPAYLOAD_FLAGS_SET(VALUE obj, unsigned short len) +{ + // as len is the only thing in the user bits, we can overwrite it every time + RPAYLOAD(obj)->flags = T_PAYLOAD | (len << FL_USHIFT); +} + typedef struct RVALUE { union { struct { VALUE flags; /* always 0 for freed obj */ struct RVALUE *next; } free; + struct RPayload payload; struct RMoved moved; struct RBasic basic; struct RObject object; @@ -660,14 +680,6 @@ typedef struct mark_stack { https://github.com/ruby/ruby/blob/trunk/gc.c#L680 size_t unused_cache_size; } mark_stack_t; -#if USE_RVARGC -#define SIZE_POOL_COUNT 4 -#else -#define SIZE_POOL_COUNT 1 -#endif -#define SIZE_POOL_EDEN_HEAP(size_pool) (&(size_pool)->eden_heap) -#define SIZE_POOL_TOMB_HEAP(size_pool) (&(size_pool)->tomb_heap) - typedef struct rb_heap_struct { struct heap_page *free_pages; struct list_head pages; @@ -681,29 +693,6 @@ typedef struct rb_heap_struct { https://github.com/ruby/ruby/blob/trunk/gc.c#L693 size_t total_slots; /* total slot count (about total_pages * HEAP_PAGE_OBJ_LIMIT) */ } rb_heap_t; -typedef struct rb_size_pool_struct { -#if USE_RVARGC - RVALUE *freelist; - struct heap_page *using_page; -#endif - - short slot_size; - - size_t allocatable_pages; - -#if USE_RVARGC - /* Sweeping statistics */ - size_t freed_slots; - size_t empty_slots; - - /* Global statistics */ - size_t force_major_gc_count; -#endif - - rb_heap_t eden_heap; - rb_heap_t tomb_heap; -} rb_size_pool_t; - enum gc_mode { gc_mode_none, gc_mode_marking, @@ -739,7 +728,8 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L728 size_t total_allocated_objects; VALUE next_object_id; - rb_size_pool_t size_pools[SIZE_POOL_COUNT]; + rb_heap_t eden_heap; + rb_heap_t tomb_heap; /* heap for zombies and ghosts */ struct { rb_atomic_t finalizing; @@ -899,8 +889,6 @@ struct heap_page { https://github.com/ruby/ruby/blob/trunk/gc.c#L889 unsigned int in_tomb : 1; } flags; - rb_size_pool_t *size_pool; - struct heap_page *free_next; RVALUE *start; RVALUE *freelist; @@ -953,10 +941,12 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; https://github.com/ruby/ruby/blob/trunk/gc.c#L941 #define heap_pages_sorted_length objspace->heap_pages.sorted_length #define heap_pages_lomem objspace->heap_pages.range[0] #define heap_pages_himem objspace->heap_pages.range[1] +#define heap_allocatable_pages objspace->heap_pages.allocatable_pages #define heap_pages_freeable_pages objspace->heap_pages.freeable_pages #define heap_pages_final_slots objspace->heap_pages.final_slots #define heap_pages_deferred_final objspace->heap_pages.deferred_final -#define size_pools objspace->size_pools +#define heap_eden (&objspace->eden_heap) +#define heap_tomb (&objspace->tomb_heap) #define during_gc objspace->flags.during_gc #define finalizing objspace->atomic_flags.finalizing #define finalizer_table objspace->finalizer_table @@ -997,69 +987,6 @@ gc_mode_verify(enum gc_mode mode) https://github.com/ruby/ruby/blob/trunk/gc.c#L987 return mode; } -static inline bool -has_sweeping_pages(rb_objspace_t *objspace) -{ - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - if (size_pools[i].eden_heap.sweeping_page) { - return TRUE; - } - } - return FALSE; -} - -static inline size_t -heap_eden_total_pages(rb_objspace_t *objspace) -{ - size_t count = 0; - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - count += size_pools[i].eden_heap.total_pages; - } - return count; -} - -static inline size_t -heap_eden_total_slots(rb_objspace_t *objspace) -{ - size_t count = 0; - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - count += size_pools[i].eden_heap.total_slots; - } - return count; -} - -static inline size_t -heap_tomb_total_pages(rb_objspace_t *objspace) -{ - size_t count = 0; - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - count += size_pools[i].tomb_heap.total_pages; - } - return count; -} - -static inline size_t -heap_allocatable_pages(rb_objspace_t *objspace) -{ - size_t count = 0; - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - count += size_pools[i].allocatable_pages; - } - return count; -} - -static inline size_t -heap_allocatable_slots(rb_objspace_t *objspace) -{ - size_t count = 0; - for (int i = 0; i < SIZE_POOL_COUNT; i++) { - rb_size_pool_t *size_pool = &size_pools[i]; - int slot_size_multiple = size_pool->slot_size / sizeof(RVALUE); - count += size_pool->allocatable_pages * HEAP_PAGE_OBJ_LIMIT / slot_size_multiple; - } - return count; -} - #define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode) #define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode)) @@ -1076,7 +1003,8 @@ heap_allocatable_slots(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L1003 #else #define will_be_incremental_marking(objspace) FALSE #endif -#define is_lazy_sweeping(objspace) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(objspace)) +#define has_sweeping_pages(heap) ((heap)->sweeping_page != 0) +#define is_lazy_sweeping(heap) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(heap)) #if SIZEOF_LONG == SIZEOF_VOIDP # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG) @@ -1148,14 +1076,14 @@ static void gc_marks(rb_objspace_t *objspace, int full_mark); https://github.com/ruby/ruby/blob/trunk/gc.c#L1076 static void gc_marks_start(rb_objspace_t *objspace, int full); static int gc_marks_finish(rb_objspace_t *objspace); static void gc_marks_rest(rb_objspace_t *objspace); -static void gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); +static void gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap); static void gc_sweep(rb_objspace_t *objspace); static void gc_sweep_start(rb_objspace_t *objspace); static void gc_sweep_finish(rb_objspace_t *objspace); -static int gc_sweep_step(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); +static int gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap); static void gc_sweep_rest(rb_objspace_t *objspace); -static void gc_sweep_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); +static void gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap); static inline void gc_mark(rb_objspace_t *objspace, VALUE ptr); static inline void gc_pin(rb_objspace_t *objspace, VALUE ptr); @@ -1362,6 +1290,36 @@ RVALUE_FLAGS_AGE(VALUE flags) https://github.com/ruby/ruby/blob/trunk/gc.c#L1290 return (int)((flags & (FL_PROMOTED0 | FL_PROMOTED1)) >> RVALUE_AGE_SHIFT); } +#if USE_RVARGC +static VALUE +payload_or_self(VALUE obj) +{ + struct heap_page *p = GET_HEAP_PAGE(obj); + VALUE cur = (VALUE)p->start; + + while (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/