зеркало из https://github.com/github/ruby.git
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 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
2bd4c51455
Коммит
c99b9eb039
30
cont.c
30
cont.c
|
@ -1411,13 +1411,20 @@ fiber_init(VALUE fibval, VALUE proc)
|
|||
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, const VALUE *argv)
|
|||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -1915,6 +1915,7 @@ void Init_BareVM(void);
|
|||
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);
|
||||
|
|
17
vm.c
17
vm.c
|
@ -2340,23 +2340,20 @@ vm_init2(rb_vm_t *vm)
|
|||
#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)
|
|||
/* 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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче