From 198ff42258d9bfde8b2056d923510c52c957b5a1 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 30 Oct 2018 22:03:42 +0000 Subject: support theap for T_STRUCT. * struct.c: members memory can use theap. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65452 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- debug_counter.h | 3 ++- gc.c | 31 ++++++++++++++++++++----------- internal.h | 11 +++++++++++ struct.c | 42 +++++++++++++++++++++++++++++++++++++++--- transient_heap.c | 20 ++++++++++---------- transient_heap.h | 3 ++- 6 files changed, 84 insertions(+), 26 deletions(-) diff --git a/debug_counter.h b/debug_counter.h index 1e7df10874..849c632f94 100644 --- a/debug_counter.h +++ b/debug_counter.h @@ -182,8 +182,9 @@ RB_DEBUG_COUNTER(obj_hash_under4) 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) diff --git a/gc.c b/gc.c index 6f3b70cc70..d819e1b3a3 100644 --- a/gc.c +++ b/gc.c @@ -2383,14 +2383,17 @@ obj_free(rb_objspace_t *objspace, VALUE obj) 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, VALUE obj) 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; imark_func_data == NULL && + RSTRUCT_TRANSIENT_P(obj)) { + rb_transient_heap_mark(obj, ptr); + } } break; diff --git a/internal.h b/internal.h index b680c8c79b..3baee61ee3 100644 --- a/internal.h +++ b/internal.h @@ -698,14 +698,18 @@ extern void ruby_init_setproctitle(int argc, char *argv[]); #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) 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 { diff --git a/struct.c b/struct.c index bed3a68ad4..b2fd1117b8 100644 --- a/struct.c +++ b/struct.c @@ -12,6 +12,7 @@ #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 values) 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) 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; diff --git a/transient_heap.c b/transient_heap.c index c1d8dbc97d..5f9962f4a0 100644 --- a/transient_heap.c +++ b/transient_heap.c @@ -354,7 +354,8 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size) 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 void *ptr) 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) 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 transient_heap* theap, struct transient_hea 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"); } diff --git a/transient_heap.h b/transient_heap.h index 0d90e4fc56..e257a8327b 100644 --- a/transient_heap.h +++ b/transient_heap.h @@ -34,6 +34,7 @@ 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); +void rb_obj_transient_heap_evacuate(VALUE obj, int promote); +void rb_struct_transient_heap_evacuate(VALUE st, int promote); #endif -- cgit v1.2.3