ruby-changes:53236
From: ko1 <ko1@a...>
Date: Wed, 31 Oct 2018 07:01:24 +0900 (JST)
Subject: [ruby-changes:53236] ko1:r65451 (trunk): support theap for T_OBJECT.
ko1 2018-10-31 07:01:17 +0900 (Wed, 31 Oct 2018) New Revision: 65451 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65451 Log: support theap for T_OBJECT. * variable.c: now instance variable space has theap supports. obj_ivar_heap_alloc() tries to acquire memory from theap. * debug_counter.h: add some counters for theap. Modified files: trunk/debug_counter.h trunk/gc.c trunk/internal.h trunk/transient_heap.c trunk/transient_heap.h trunk/variable.c Index: debug_counter.h =================================================================== --- debug_counter.h (revision 65450) +++ debug_counter.h (revision 65451) @@ -141,6 +141,7 @@ RB_DEBUG_COUNTER(gc_major_oldmalloc) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L141 * * [attr] * * _ptr: R?? is not embed. * * _embed: R?? is embed. + * * _transient: R?? uses transient heap. * * type specific attr. * * str_shared: str is shared. * * str_nofree: nofree @@ -162,8 +163,9 @@ RB_DEBUG_COUNTER(obj_free) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L163 RB_DEBUG_COUNTER(obj_promote) RB_DEBUG_COUNTER(obj_wb_unprotect) -RB_DEBUG_COUNTER(obj_obj_ptr) RB_DEBUG_COUNTER(obj_obj_embed) +RB_DEBUG_COUNTER(obj_obj_transient) +RB_DEBUG_COUNTER(obj_obj_ptr) RB_DEBUG_COUNTER(obj_str_ptr) RB_DEBUG_COUNTER(obj_str_embed) @@ -171,8 +173,9 @@ RB_DEBUG_COUNTER(obj_str_shared) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L173 RB_DEBUG_COUNTER(obj_str_nofree) RB_DEBUG_COUNTER(obj_str_fstr) -RB_DEBUG_COUNTER(obj_ary_ptr) RB_DEBUG_COUNTER(obj_ary_embed) +RB_DEBUG_COUNTER(obj_ary_transient) +RB_DEBUG_COUNTER(obj_ary_ptr) RB_DEBUG_COUNTER(obj_hash_empty) RB_DEBUG_COUNTER(obj_hash_under4) Index: transient_heap.c =================================================================== --- transient_heap.c (revision 65450) +++ transient_heap.c (revision 65451) @@ -353,7 +353,8 @@ rb_transient_heap_alloc(VALUE obj, size_ https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L353 struct transient_heap* theap = transient_heap_get(); size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN); - TH_ASSERT(RB_TYPE_P(obj, T_ARRAY)); /* supported types */ + TH_ASSERT(RB_TYPE_P(obj, T_ARRAY) || + RB_TYPE_P(obj, T_OBJECT)); /* supported types */ if (size > TRANSIENT_HEAP_ALLOC_MAX) { if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [too big: %ld] %s\n", (long)size, rb_obj_info(obj)); @@ -557,6 +558,14 @@ transient_heap_ptr(VALUE obj, int error) https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L558 ptr = NULL; } break; + case T_OBJECT: + if (ROBJ_TRANSIENT_P(obj)) { + ptr = ROBJECT_IVPTR(obj); + } + else { + ptr = NULL; + } + break; default: if (error) { rb_bug("transient_heap_ptr: unknown obj %s\n", rb_obj_info(obj)); @@ -659,11 +668,10 @@ transient_heap_block_evacuate(struct tra https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L668 switch (BUILTIN_TYPE(obj)) { case T_ARRAY: -#if TRANSIENT_HEAP_DEBUG_DONT_PROMOTE - rb_ary_transient_heap_evacuate(obj, FALSE); -#else - rb_ary_transient_heap_evacuate(obj, TRUE); -#endif + rb_ary_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE); + break; + case T_OBJECT: + rb_obj_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE); break; default: rb_bug("unsupporeted"); Index: transient_heap.h =================================================================== --- transient_heap.h (revision 65450) +++ transient_heap.h (revision 65451) @@ -34,5 +34,6 @@ int rb_transient_heap_managed_ptr_p(con https://github.com/ruby/ruby/blob/trunk/transient_heap.h#L34 /* evacuate functions */ void rb_ary_transient_heap_evacuate(VALUE ary, int promote); +void rb_obj_transient_heap_evacuate(VALUE ary, int promote); #endif Index: gc.c =================================================================== --- gc.c (revision 65450) +++ gc.c (revision 65451) @@ -2215,15 +2215,18 @@ obj_free(rb_objspace_t *objspace, VALUE https://github.com/ruby/ruby/blob/trunk/gc.c#L2215 switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) && - RANY(obj)->as.object.as.heap.ivptr) { - xfree(RANY(obj)->as.object.as.heap.ivptr); - RB_DEBUG_COUNTER_INC(obj_obj_ptr); + if ((RANY(obj)->as.basic.flags & ROBJECT_EMBED) || + RANY(obj)->as.object.as.heap.ivptr == NULL) { + RB_DEBUG_COUNTER_INC(obj_obj_embed); + } + else if (ROBJ_TRANSIENT_P(obj)) { + RB_DEBUG_COUNTER_INC(obj_obj_transient); } else { - RB_DEBUG_COUNTER_INC(obj_obj_embed); + xfree(RANY(obj)->as.object.as.heap.ivptr); + RB_DEBUG_COUNTER_INC(obj_obj_ptr); } - break; + break; case T_MODULE: case T_CLASS: mjit_remove_class_serial(RCLASS_SERIAL(obj)); @@ -4717,10 +4720,18 @@ gc_mark_children(rb_objspace_t *objspace https://github.com/ruby/ruby/blob/trunk/gc.c#L4720 case T_OBJECT: { - uint32_t i, len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); - for (i = 0; i < len; i++) { - gc_mark(objspace, *ptr++); + const VALUE * const ptr = ROBJECT_IVPTR(obj); + + if (ptr) { + uint32_t i, len = ROBJECT_NUMIV(obj); + for (i = 0; i < len; i++) { + gc_mark(objspace, ptr[i]); + } + + if (objspace->mark_func_data == NULL && + ROBJ_TRANSIENT_P(obj)) { + rb_transient_heap_mark(obj, ptr); + } } } break; @@ -9645,6 +9656,19 @@ rb_raw_obj_info(char *buff, const int bu https://github.com/ruby/ruby/blob/trunk/gc.c#L9656 } break; } + case T_OBJECT: + { + uint32_t len = ROBJECT_NUMIV(obj); + + if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) { + snprintf(buff, buff_size, "%s (embed) len:%d", buff, len); + } + else { + VALUE *ptr = ROBJECT_IVPTR(obj); + snprintf(buff, buff_size, "%s len:%d ptr:%p", buff, len, ptr); + } + } + break; case T_DATA: { const struct rb_block *block; const rb_iseq_t *iseq; Index: internal.h =================================================================== --- internal.h (revision 65450) +++ internal.h (revision 65451) @@ -1922,6 +1922,9 @@ extern rb_encoding OnigEncodingUTF_8; https://github.com/ruby/ruby/blob/trunk/internal.h#L1922 #endif /* variable.c */ +#define ROBJECT_TRANSIENT_FLAG FL_USER13 +#define ROBJ_TRANSIENT_P(obj) FL_TEST_RAW((obj), ROBJECT_TRANSIENT_FLAG) + void rb_gc_mark_global_tbl(void); size_t rb_generic_ivar_memsize(VALUE); VALUE rb_search_class_path(VALUE); Index: variable.c =================================================================== --- variable.c (revision 65450) +++ variable.c (revision 65451) @@ -22,6 +22,7 @@ https://github.com/ruby/ruby/blob/trunk/variable.c#L22 #include "id_table.h" #include "debug_counter.h" #include "vm_core.h" +#include "transient_heap.h" static struct rb_id_table *rb_global_tbl; static ID autoload, classpath, tmp_classpath, classid; @@ -1333,61 +1334,132 @@ generic_ivar_set(VALUE obj, ID id, VALUE https://github.com/ruby/ruby/blob/trunk/variable.c#L1334 RB_OBJ_WRITTEN(obj, Qundef, val); } -VALUE -rb_ivar_set(VALUE obj, ID id, VALUE val) +static VALUE * +obj_ivar_heap_alloc(VALUE obj, size_t newsize) +{ + VALUE *newptr = rb_transient_heap_alloc(obj, sizeof(VALUE) * newsize); + + if (newptr != NULL) { + FL_SET_RAW(obj, ROBJECT_TRANSIENT_FLAG); + } + else { + FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG); + newptr = ALLOC_N(VALUE, newsize); + } + return newptr; +} + +static VALUE * +obj_ivar_heap_realloc(VALUE obj, int32_t len, size_t newsize) +{ + VALUE *newptr; + int i; + + if (ROBJ_TRANSIENT_P(obj)) { + const VALUE *orig_ptr = ROBJECT(obj)->as.heap.ivptr; + if ((newptr = obj_ivar_heap_alloc(obj, newsize)) != NULL) { + /* ok */ + } + else { + newptr = ALLOC_N(VALUE, newsize); + FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG); + } + ROBJECT(obj)->as.heap.ivptr = newptr; + for (i=0; i<(int)len; i++) { + newptr[i] = orig_ptr[i]; + } + } + else { + REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize); + newptr = ROBJECT(obj)->as.heap.ivptr; + } + + return newptr; +} + +void +rb_obj_transient_heap_evacuate(VALUE obj, int promote) +{ + if (ROBJ_TRANSIENT_P(obj)) { + uint32_t len = ROBJECT_NUMIV(obj); + const VALUE *old_ptr = ROBJECT_IVPTR(obj); + VALUE *new_ptr; + + if (promote) { + new_ptr = ALLOC_N(VALUE, len); + FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG); + } + else { + new_ptr = obj_ivar_heap_alloc(obj, len); + } + MEMCPY(new_ptr, old_ptr, VALUE, len); + ROBJECT(obj)->as.heap.ivptr = new_ptr; + } +} + +static VALUE +obj_ivar_set(VALUE obj, ID id, VALUE val) { struct ivar_update ivup; uint32_t i, len; + ivup.iv_extended = 0; + ivup.u.iv_index_tbl = iv_index_tbl_make(obj); + iv_index_tbl_extend(&ivup, id); + len = ROBJECT_NUMIV(obj); + if (len <= ivup.index) { + VALUE *ptr = ROBJECT_IVPTR(obj); + if (ivup.index < ROBJECT_EMBED_LEN_MAX) { + RBASIC(obj)->flags |= ROBJECT_EMBED; + ptr = ROBJECT(obj)->as.ary; + for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { + ptr[i] = Qundef; + } + } + else { + VALUE *newptr; + uint32_t newsize = iv_index_tbl_newsize(&ivup); + + if (RBASIC(obj)->flags & ROBJECT_EMBED) { + newptr = obj_ivar_heap_alloc(obj, newsize); + // newptr = ALLOC_N(VALUE, newsize); + MEMCPY(newptr, ptr, VALUE, len); + RBASIC(obj)->flags &= ~ROBJECT_EMBED; + ROBJECT(obj)->as.heap.ivptr = newptr; + } + else { + newptr = obj_ivar_heap_realloc(obj, len, newsize); + } + for (; len < newsize; len++) { + newptr[len] = Qundef; + } + ROBJECT(obj)->as.heap.numiv = newsize; + ROBJECT(obj)->as.heap.iv_index_tbl = ivup.u.iv_index_tbl; + } + } + RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val); + + return val; +} + +VALUE +rb_ivar_set(VALUE obj, ID id, VALUE val) +{ RB_DEBUG_COUNTER_INC(ivar_set_base); rb_check_frozen(obj); switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - ivup.iv_extended = 0; - ivup.u.iv_index_tbl = iv_index_tbl_make(obj); - iv_index_tbl_extend(&ivup, id); - len = ROBJECT_NUMIV(obj); - if (len <= ivup.index) { - VALUE *ptr = ROBJECT_IVPTR(obj); - if (ivup.index < ROBJECT_EMBED_LEN_MAX) { - RBASIC(obj)->flags |= ROBJECT_EMBED; - ptr = ROBJECT(obj)->as.ary; - for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { - ptr[i] = Qundef; - } - } - else { - VALUE *newptr; - uint32_t newsize = iv_index_tbl_newsize(&ivup); - - if (RBASIC(obj)->flags & ROBJECT_EMBED) { - newptr = ALLOC_N(VALUE, newsize); - MEMCPY(newptr, ptr, VALUE, len); - RBASIC(obj)->flags &= ~ROBJECT_EMBED; - ROBJECT(obj)->as.heap.ivptr = newptr; - } - else { - REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize); - newptr = ROBJECT(obj)->as.heap.ivptr; - } - for (; len < newsize; len++) - newptr[len] = Qundef; - ROBJECT(obj)->as.heap.numiv = newsize; - ROBJECT(obj)->as.heap.iv_index_tbl = ivup.u.iv_index_tbl; - } - } - RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val); - break; + return obj_ivar_set(obj, id, val); case T_CLASS: case T_MODULE: - if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); - rb_class_ivar_set(obj, id, val); + if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); + rb_class_ivar_set(obj, id, val); break; default: - generic_ivar_set(obj, id, val); - break; + generic_ivar_set(obj, id, val); + break; } return val; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/