ruby-changes:53237
From: ko1 <ko1@a...>
Date: Wed, 31 Oct 2018 07:03:47 +0900 (JST)
Subject: [ruby-changes:53237] ko1:r65452 (trunk): support theap for T_STRUCT.
ko1 2018-10-31 07:03:42 +0900 (Wed, 31 Oct 2018) New Revision: 65452 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65452 Log: support theap for T_STRUCT. * struct.c: members memory can use theap. Modified files: trunk/debug_counter.h trunk/gc.c trunk/internal.h trunk/struct.c trunk/transient_heap.c trunk/transient_heap.h Index: debug_counter.h =================================================================== --- debug_counter.h (revision 65451) +++ debug_counter.h (revision 65452) @@ -182,8 +182,9 @@ RB_DEBUG_COUNTER(obj_hash_under4) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L182 RB_DEBUG_COUNTER(obj_hash_ge4) RB_DEBUG_COUNTER(obj_hash_ge8) -RB_DEBUG_COUNTER(obj_struct_ptr) RB_DEBUG_COUNTER(obj_struct_embed) +RB_DEBUG_COUNTER(obj_struct_transient) +RB_DEBUG_COUNTER(obj_struct_ptr) RB_DEBUG_COUNTER(obj_regexp_ptr) Index: internal.h =================================================================== --- internal.h (revision 65451) +++ internal.h (revision 65452) @@ -698,14 +698,18 @@ extern void ruby_init_setproctitle(int a https://github.com/ruby/ruby/blob/trunk/internal.h#L698 #define RSTRUCT_EMBED_LEN_MAX RSTRUCT_EMBED_LEN_MAX #define RSTRUCT_EMBED_LEN_MASK RSTRUCT_EMBED_LEN_MASK #define RSTRUCT_EMBED_LEN_SHIFT RSTRUCT_EMBED_LEN_SHIFT + enum { RSTRUCT_EMBED_LEN_MAX = 3, RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1), RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1), + RSTRUCT_TRANSIENT_FLAG = FL_USER3, RSTRUCT_ENUM_END }; +#define RSTRUCT_TRANSIENT_P(st) FL_TEST_RAW((obj), RSTRUCT_TRANSIENT_FLAG) + struct RStruct { struct RBasic basic; union { @@ -746,6 +750,13 @@ rb_struct_const_ptr(VALUE st) https://github.com/ruby/ruby/blob/trunk/internal.h#L750 RSTRUCT(st)->as.ary : RSTRUCT(st)->as.heap.ptr); } +static inline const VALUE * +rb_struct_const_heap_ptr(VALUE st) +{ + /* TODO: check embed on debug mode */ + return RSTRUCT(st)->as.heap.ptr; +} + /* class.c */ struct rb_deprecated_classext_struct { Index: transient_heap.c =================================================================== --- transient_heap.c (revision 65451) +++ transient_heap.c (revision 65452) @@ -354,7 +354,8 @@ rb_transient_heap_alloc(VALUE obj, size_ https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L354 size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN); TH_ASSERT(RB_TYPE_P(obj, T_ARRAY) || - RB_TYPE_P(obj, T_OBJECT)); /* supported types */ + RB_TYPE_P(obj, T_OBJECT) || + RB_TYPE_P(obj, T_STRUCT)); /* 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)); @@ -546,7 +547,7 @@ rb_transient_heap_mark(VALUE obj, const https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L547 static const void * transient_heap_ptr(VALUE obj, int error) { - const void *ptr; + const void *ptr = NULL; switch (BUILTIN_TYPE(obj)) { case T_ARRAY: @@ -554,25 +555,21 @@ transient_heap_ptr(VALUE obj, int error) https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L555 TH_ASSERT(!FL_TEST_RAW(obj, RARRAY_EMBED_FLAG)); ptr = RARRAY(obj)->as.heap.ptr; } - else { - ptr = NULL; - } break; case T_OBJECT: if (ROBJ_TRANSIENT_P(obj)) { ptr = ROBJECT_IVPTR(obj); } - else { - ptr = NULL; + break; + case T_STRUCT: + if (RSTRUCT_TRANSIENT_P(obj)) { + ptr = rb_struct_const_heap_ptr(obj); } break; default: if (error) { rb_bug("transient_heap_ptr: unknown obj %s\n", rb_obj_info(obj)); } - else { - ptr = NULL; - } } return ptr; @@ -673,6 +670,9 @@ transient_heap_block_evacuate(struct tra https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L670 case T_OBJECT: rb_obj_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE); break; + case T_STRUCT: + rb_struct_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE); + break; default: rb_bug("unsupporeted"); } Index: transient_heap.h =================================================================== --- transient_heap.h (revision 65451) +++ transient_heap.h (revision 65452) @@ -34,6 +34,7 @@ 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); +void rb_obj_transient_heap_evacuate(VALUE obj, int promote); +void rb_struct_transient_heap_evacuate(VALUE st, int promote); #endif Index: struct.c =================================================================== --- struct.c (revision 65451) +++ struct.c (revision 65452) @@ -12,6 +12,7 @@ https://github.com/ruby/ruby/blob/trunk/struct.c#L12 #include "internal.h" #include "vm_core.h" #include "id.h" +#include "transient_heap.h" /* only for struct[:field] access */ enum { @@ -654,6 +655,41 @@ rb_struct_initialize(VALUE self, VALUE v https://github.com/ruby/ruby/blob/trunk/struct.c#L655 return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self); } +static VALUE * +struct_heap_alloc(VALUE st, size_t len) +{ + VALUE *ptr = rb_transient_heap_alloc((VALUE)st, sizeof(VALUE) * len); + + if (ptr) { + FL_SET_RAW(st, RSTRUCT_TRANSIENT_FLAG); + return ptr; + } + else { + FL_UNSET_RAW(st, RSTRUCT_TRANSIENT_FLAG); + return ALLOC_N(VALUE, len); + } +} + +void +rb_struct_transient_heap_evacuate(VALUE obj, int promote) +{ + if (RSTRUCT_TRANSIENT_P(obj)) { + const VALUE *old_ptr = rb_struct_const_heap_ptr(obj); + VALUE *new_ptr; + long len = RSTRUCT_LEN(obj); + + if (promote) { + new_ptr = ALLOC_N(VALUE, len); + FL_UNSET_RAW(obj, RSTRUCT_TRANSIENT_FLAG); + } + else { + new_ptr = struct_heap_alloc(obj, len); + } + MEMCPY(new_ptr, old_ptr, VALUE, len); + RSTRUCT(obj)->as.heap.ptr = new_ptr; + } +} + static VALUE struct_alloc(VALUE klass) { @@ -668,9 +704,9 @@ struct_alloc(VALUE klass) https://github.com/ruby/ruby/blob/trunk/struct.c#L704 rb_mem_clear((VALUE *)st->as.ary, n); } else { - st->as.heap.ptr = ALLOC_N(VALUE, n); - rb_mem_clear((VALUE *)st->as.heap.ptr, n); - st->as.heap.len = n; + st->as.heap.ptr = struct_heap_alloc((VALUE)st, n); + rb_mem_clear((VALUE *)st->as.heap.ptr, n); + st->as.heap.len = n; } return (VALUE)st; Index: gc.c =================================================================== --- gc.c (revision 65451) +++ gc.c (revision 65452) @@ -2383,14 +2383,17 @@ obj_free(rb_objspace_t *objspace, VALUE https://github.com/ruby/ruby/blob/trunk/gc.c#L2383 break; case T_STRUCT: - if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && - RANY(obj)->as.rstruct.as.heap.ptr) { - xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr); - RB_DEBUG_COUNTER_INC(obj_struct_ptr); - } - else { + if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) || + RANY(obj)->as.rstruct.as.heap.ptr == NULL) { RB_DEBUG_COUNTER_INC(obj_struct_embed); } + else if (RSTRUCT_TRANSIENT_P(obj)) { + RB_DEBUG_COUNTER_INC(obj_struct_transient); + } + else { + xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr); + RB_DEBUG_COUNTER_INC(obj_struct_ptr); + } break; case T_SYMBOL: @@ -4775,12 +4778,18 @@ gc_mark_children(rb_objspace_t *objspace https://github.com/ruby/ruby/blob/trunk/gc.c#L4778 case T_STRUCT: { - long len = RSTRUCT_LEN(obj); - const VALUE *ptr = RSTRUCT_CONST_PTR(obj); + long i; + const long len = RSTRUCT_LEN(obj); + const VALUE * const ptr = RSTRUCT_CONST_PTR(obj); - while (len--) { - gc_mark(objspace, *ptr++); - } + for (i=0; i<len; i++) { + gc_mark(objspace, ptr[i]); + } + + if (objspace->mark_func_data == NULL && + RSTRUCT_TRANSIENT_P(obj)) { + rb_transient_heap_mark(obj, ptr); + } } break; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/