[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]