From 873d57347fca4fc7f407c2bca45f90797ab6f864 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 30 Oct 2018 22:01:17 +0000 Subject: 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65451 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- debug_counter.h | 7 ++- gc.c | 44 ++++++++++++---- internal.h | 3 ++ transient_heap.c | 20 +++++--- transient_heap.h | 1 + variable.c | 154 ++++++++++++++++++++++++++++++++++++++++--------------- 6 files changed, 170 insertions(+), 59 deletions(-) diff --git a/debug_counter.h b/debug_counter.h index c151e535b0..1e7df10874 100644 --- a/debug_counter.h +++ b/debug_counter.h @@ -141,6 +141,7 @@ RB_DEBUG_COUNTER(gc_major_oldmalloc) * * [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) 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) 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) diff --git a/gc.c b/gc.c index 868e58dd65..6f3b70cc70 100644 --- a/gc.c +++ b/gc.c @@ -2215,15 +2215,18 @@ obj_free(rb_objspace_t *objspace, VALUE obj) 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, VALUE obj) 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 buff_size, VALUE obj) } 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; diff --git a/internal.h b/internal.h index ffe84528db..b680c8c79b 100644 --- a/internal.h +++ b/internal.h @@ -1922,6 +1922,9 @@ extern rb_encoding OnigEncodingUTF_8; #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); diff --git a/transient_heap.c b/transient_heap.c index e9a2460d88..c1d8dbc97d 100644 --- a/transient_heap.c +++ b/transient_heap.c @@ -353,7 +353,8 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size) 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) 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 transient_heap* theap, struct transient_hea 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"); diff --git a/transient_heap.h b/transient_heap.h index ac0eaadb78..0d90e4fc56 100644 --- a/transient_heap.h +++ b/transient_heap.h @@ -34,5 +34,6 @@ int rb_transient_heap_managed_ptr_p(const void *ptr); /* evacuate functions */ void rb_ary_transient_heap_evacuate(VALUE ary, int promote); +void rb_obj_transient_heap_evacuate(VALUE ary, int promote); #endif diff --git a/variable.c b/variable.c index ee8807c838..1781c82ce4 100644 --- a/variable.c +++ b/variable.c @@ -22,6 +22,7 @@ #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 val) 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; } -- cgit v1.2.3