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

ruby-changes:52494

From: normal <ko1@a...>
Date: Thu, 13 Sep 2018 05:49:17 +0900 (JST)
Subject: [ruby-changes:52494] normal:r64703 (trunk): share VM stack between threads and fibers if identical in size

normal	2018-09-13 05:49:10 +0900 (Thu, 13 Sep 2018)

  New Revision: 64703

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64703

  Log:
    share VM stack between threads and fibers if identical in size
    
    ec->vm_stack is always allocated with malloc, so stack cache for
    root fiber (thread stack) and non-root fibers can be shared as
    long as the size is the same.  The purpose of this change is to
    reduce dependencies on ROOT_FIBER_CONTEXT.
    
    [Feature #15095] [Bug #15050]
    
    v2: vm.c: fix build with USE_THREAD_DATA_RECYCLE==0

  Modified files:
    trunk/cont.c
    trunk/internal.h
    trunk/vm.c
Index: internal.h
===================================================================
--- internal.h	(revision 64702)
+++ internal.h	(revision 64703)
@@ -1915,6 +1915,7 @@ void Init_BareVM(void); https://github.com/ruby/ruby/blob/trunk/internal.h#L1915
 void Init_vm_objects(void);
 PUREFUNC(VALUE rb_vm_top_self(void));
 void rb_thread_recycle_stack_release(VALUE *);
+VALUE *rb_thread_recycle_stack(size_t);
 void rb_vm_change_state(void);
 void rb_vm_inc_const_missing_count(void);
 const void **rb_vm_get_insns_address_table(void);
Index: vm.c
===================================================================
--- vm.c	(revision 64702)
+++ vm.c	(revision 64703)
@@ -2340,23 +2340,20 @@ vm_init2(rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/vm.c#L2340
 #define RECYCLE_MAX 64
 static VALUE *thread_recycle_stack_slot[RECYCLE_MAX];
 static int thread_recycle_stack_count = 0;
+#endif /* USE_THREAD_DATA_RECYCLE */
 
-static VALUE *
-thread_recycle_stack(size_t size)
+VALUE *
+rb_thread_recycle_stack(size_t size)
 {
+#if USE_THREAD_DATA_RECYCLE
     if (thread_recycle_stack_count > 0) {
 	/* TODO: check stack size if stack sizes are variable */
 	return thread_recycle_stack_slot[--thread_recycle_stack_count];
     }
-    else {
-	return ALLOC_N(VALUE, size);
-    }
+#endif /* USE_THREAD_DATA_RECYCLE */
+    return ALLOC_N(VALUE, size);
 }
 
-#else
-#define thread_recycle_stack(size) ALLOC_N(VALUE, (size))
-#endif
-
 void
 rb_thread_recycle_stack_release(VALUE *stack)
 {
@@ -2536,7 +2533,7 @@ th_init(rb_thread_t *th, VALUE self) https://github.com/ruby/ruby/blob/trunk/vm.c#L2533
 	/* vm_stack_size is word number.
 	 * th->vm->default_params.thread_vm_stack_size is byte size. */
 	size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
-	ec_set_vm_stack(th->ec, thread_recycle_stack(size), size);
+	ec_set_vm_stack(th->ec, rb_thread_recycle_stack(size), size);
     }
 
     th->ec->cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size);
Index: cont.c
===================================================================
--- cont.c	(revision 64702)
+++ cont.c	(revision 64703)
@@ -1411,13 +1411,20 @@ fiber_init(VALUE fibval, VALUE proc) https://github.com/ruby/ruby/blob/trunk/cont.c#L1411
     rb_context_t *cont = &fib->cont;
     rb_execution_context_t *sec = &cont->saved_ec;
     rb_thread_t *cth = GET_THREAD();
-    size_t fib_stack_size = cth->vm->default_params.fiber_vm_stack_size / sizeof(VALUE);
+    rb_vm_t *vm = cth->vm;
+    size_t fib_stack_bytes = vm->default_params.fiber_vm_stack_size;
+    size_t thr_stack_bytes = vm->default_params.thread_vm_stack_size;
+    VALUE *vm_stack;
 
     /* initialize cont */
     cont->saved_vm_stack.ptr = NULL;
-    ec_set_vm_stack(sec, NULL, 0);
-
-    ec_set_vm_stack(sec, ALLOC_N(VALUE, fib_stack_size), fib_stack_size);
+    if (fib_stack_bytes == thr_stack_bytes) {
+        vm_stack = rb_thread_recycle_stack(fib_stack_bytes / sizeof(VALUE));
+    }
+    else {
+        vm_stack = ruby_xmalloc(fib_stack_bytes);
+    }
+    ec_set_vm_stack(sec, vm_stack, fib_stack_bytes / sizeof(VALUE));
     sec->cfp = (void *)(sec->vm_stack + sec->vm_stack_size);
 
     rb_vm_push_frame(sec,
@@ -1758,19 +1765,22 @@ rb_fiber_transfer(VALUE fibval, int argc https://github.com/ruby/ruby/blob/trunk/cont.c#L1765
 void
 rb_fiber_close(rb_fiber_t *fib)
 {
-    VALUE *vm_stack = fib->cont.saved_ec.vm_stack;
+    rb_execution_context_t *ec = &fib->cont.saved_ec;
+    VALUE *vm_stack = ec->vm_stack;
+    size_t stack_bytes = ec->vm_stack_size * sizeof(VALUE);
+
     fiber_status_set(fib, FIBER_TERMINATED);
-    if (fib->cont.type == ROOT_FIBER_CONTEXT) {
-	rb_thread_recycle_stack_release(vm_stack);
+    if (stack_bytes == rb_ec_vm_ptr(ec)->default_params.thread_vm_stack_size) {
+        rb_thread_recycle_stack_release(vm_stack);
     }
     else {
-	ruby_xfree(vm_stack);
+        ruby_xfree(vm_stack);
     }
-    ec_set_vm_stack(&fib->cont.saved_ec, NULL, 0);
+    ec_set_vm_stack(ec, NULL, 0);
 
 #if !FIBER_USE_NATIVE
     /* should not mark machine stack any more */
-    fib->cont.saved_ec.machine.stack_end = NULL;
+    ec->machine.stack_end = NULL;
 #endif
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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