以下の6つの機能を分離し、簡単に切り替えられるようにしたい。
- OSからのメモリアロケータ
- OSからメモリアロケートする部分のAPI
- Rubyのヒープ管理
- ヒープの設定を保持
- e.g. malloc_limit,heap_min_slots...
- オブジェクトの情報を提供
- e.g. is_pointer_heap(), is_dead/live_object()...
- ObjectSpaceモジュールのAPI提供
- e.g. ObjectSpace.count_objects(),_id2ref(),each_object()...
- GCアルゴリズム
- マークフェーズの関数
- スイープフェーズの関数
- GCモジュール用のstart,enable,disable,count
- e.g. GC.start(),enable(),disable(),count()..
- ヒープとGCは一体にする
- e.g. GC.start(),enable(),disable(),count()..
- オブジェクトのアロケータ
- オブジェクトの型を受け取って割り当てたオブジェクトを返す
- こっちもヒープ管理のAPIで提供
- オブジェクトのfree
- オブジェクトを受け取ってfreeするもの
- GCプロファイラのAPI
- もうちょっと切り替えやすいもの
API化が不要なものは(不要)マークを付けておく。
- rb_newobj
- rb_node_newnode
- rb_data_object_alloc
- rb_data_typed_object_alloc
- rb_gc_set_params
- rb_objspace_alloc
- rb_objspace_free
- rb_memerror
- ruby_xmalloc2
- ruby_xcalloc
- ruby_xrealloc
- ruby_xrealloc2
- ruby_xfree
- ruby_mimmalloc (不要)
- rb_gc_register_mark_object (不要)
- rb_gc_register_address (不要)
- rb_global_variable (不要)
- rb_gc_unregister_address (不要)
- rb_during_gc
- ruby_get_stack_grow_direction (不要)
- ruby_stack_length (不要)
- ruby_stack_check (不要)
- rb_gc_mark_locations
- rb_mark_set
- rb_mark_hash
- rb_mark_method_entry
- rb_free_m_table
- rb_free_const_table
- rb_mark_tbl
- rb_gc_mark_maybe
- rb_gc_mark
- rb_garbage_collect
- rb_gc_mark_machine_stack
- rb_gc_start
- rb_gc_force_recycle
- Init_stack (不要)
- Init_heap
- rb_objspace_each_objects
- rb_undefine_final (不要)
- rb_define_final (不要)
- rb_gc_copy_finalizer (不要)
- rb_gc_finalize_deferred (不要)
- rb_gc_call_finalizer_at_exit (不要)
- rb_gc
- rb_obj_id
-
GC
- gc_stress_get
- gc_stress_set
- rb_gc_enable
- rb_gc_disable
- gc_count
- gc_stat
- rb_gc_start
- gc_malloc_allocated_size
- gc_malloc_allocations
-
GC::Profiler
- gc_profile_enable_get
- gc_profile_enable
- gc_profile_disable
- gc_profile_clear
- gc_profile_record_get
- gc_profile_total_time
- gc_profile_result
- gc_profile_report
- gc_profile_disable
- gc_profile_clear
-
Objspace
- os_each_obj
- rb_gc_start
- define_final
- undefine_final
- rb_objspace_data_type_memsize
- rb_objspace_data_type_name
- id2ref
- count_objects
-
Objspace::WeakMap (独立しているため共通のもので良さそう)
- wmap_allocate
- wmap_aset
- wmap_aref
- wmap_finalize
typedef struct {
union {
struct rb_ms_objspace_t ms;
struct rb_bitmap_ms_objspace_t bitmap;
} as;
} rb_objspace_t;
#define RB_OBJSPACE_API\
共通API群;
#define RB_OBJSPACE_VALUES\
共通の変数群;
typedef struct {
RB_OBJSPACE_API;
RB_OBJSPACE_VALUES;
MSの変数群;
} rb_ms_objspace_t;
typedef struct {
RB_OBJSPACE_API;
RB_OBJSPACE_VALUES;
BitmapMS用フラグ群;
} rb_bitmap_ms_objspace_t;
- void alloc(rb_objspace_t *objspace);
- rb_objspace_alloc
- void free(rb_objspace_t *objspace);
- rb_objspace_free
- VALUE obj_alloc(VALUE klass);
- klassが指定されなかったらT_NONEとする
- void obj_free(VALUE);
- void * xcalloc(size_t count, size_t elsize);
- void * xmalloc(size_t size)
- void xfree(ptr)
- ruby_xmalloc2, ruby_xcalloc, ruby_xrealloc, ruby_xrealloc2, ruby_xfree
- void init_heap(rb_objspace_t *objspace)
- int garbage_collect(rb_objspace_t *objspace)
- VALUE objspace_each_objects(VALUE arg)
- int count_objects(int argc, VALUE *argv, VALUE os)
- void gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev);
- int is_pointer_to_heap(rb_objspace_t *objspace, ptr);
- int is_dead_object(rb_objspace_t *objspace, ptr);
- int is_live_object(rb_objspace_t *objspace, ptr);
- VALUE id2ref(rb_objspace_t *objspace, VALUE obj, VALUE objid);
- void force_recycle(rb_objspace_t *objspace, VALUE p);
- void finish_finalize(rb_objspace_t *objspace, VALUE p);
- finalizeしたあとでslotのlimit削る
- flags
- int dont_gc;
- int during_gc;
- int stress;
- rb_atomic finalizing;
- size_t count;
- int gc_stress;
- malloc_params
- size_t limit;
- size_t increase;
- size_t allocated_size;
- size_t allocations;
- struct gc_list *global_list;
- gc_profiler *profiler
実装イメージ:
profiler系は別ファイルの構造体で管理する。
typedef struct gc_profile_record {
...;
} gc_profile_record;
typedef struct gc_profiler {
gc_profile_record *records;
void (*profile) (rb_objspace_t objspace, enum gc_profile_type);
} gc_profiler_t;
- gc_profile(rb_objspace_t objspace, enum gc_profile_type, ...)
- 上記の関数だけ提供
- final
- st_table *table;
- RVALUE *deferred;
Finalizer系は共通の関数でよいだろう。