summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2019-05-31 13:25:24 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2019-06-11 09:16:14 -0700
commit6db2d6d8520f88e25d97af77495eb6c879f90b21 (patch)
tree25c42ae8e1a14a019a37401d65ad32f10aa506c6
parentc4cbaef216ffcc9bda70cc328a805ad679ccaa8c (diff)
Add compaction support for more types.
This commit adds compaction support for: * Fibers * Continuations * Autoload Constants
-rw-r--r--cont.c42
-rw-r--r--proc.c5
-rw-r--r--variable.c18
-rw-r--r--vm.c51
-rw-r--r--vm_core.h1
5 files changed, 103 insertions, 14 deletions
diff --git a/cont.c b/cont.c
index 516a847b9e..0d091b9169 100644
--- a/cont.c
+++ b/cont.c
@@ -340,12 +340,21 @@ cont_thread_value(const rb_context_t *cont)
}
static void
+cont_compact(void *ptr)
+{
+ rb_context_t *cont = ptr;
+
+ cont->value = rb_gc_location(cont->value);
+ rb_execution_context_update(&cont->saved_ec);
+}
+
+static void
cont_mark(void *ptr)
{
rb_context_t *cont = ptr;
RUBY_MARK_ENTER("cont");
- rb_gc_mark(cont->value);
+ rb_gc_mark_no_pin(cont->value);
rb_execution_context_mark(&cont->saved_ec);
rb_gc_mark(cont_thread_value(cont));
@@ -481,10 +490,21 @@ cont_memsize(const void *ptr)
}
void
+rb_fiber_update_self(rb_fiber_t *fib)
+{
+ if (fib->cont.self) {
+ fib->cont.self = rb_gc_location(fib->cont.self);
+ }
+ else {
+ rb_execution_context_update(&fib->cont.saved_ec);
+ }
+}
+
+void
rb_fiber_mark_self(const rb_fiber_t *fib)
{
if (fib->cont.self) {
- rb_gc_mark(fib->cont.self);
+ rb_gc_mark_no_pin(fib->cont.self);
}
else {
rb_execution_context_mark(&fib->cont.saved_ec);
@@ -492,12 +512,24 @@ rb_fiber_mark_self(const rb_fiber_t *fib)
}
static void
+fiber_compact(void *ptr)
+{
+ rb_fiber_t *fib = ptr;
+ fib->first_proc = rb_gc_location(fib->first_proc);
+
+ if (fib->prev) rb_fiber_update_self(fib->prev);
+
+ cont_compact(&fib->cont);
+ fiber_verify(fib);
+}
+
+static void
fiber_mark(void *ptr)
{
rb_fiber_t *fib = ptr;
RUBY_MARK_ENTER("cont");
fiber_verify(fib);
- rb_gc_mark(fib->first_proc);
+ rb_gc_mark_no_pin(fib->first_proc);
if (fib->prev) rb_fiber_mark_self(fib->prev);
#if !FIBER_USE_NATIVE
@@ -602,7 +634,7 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
static const rb_data_type_t cont_data_type = {
"continuation",
- {cont_mark, cont_free, cont_memsize,},
+ {cont_mark, cont_free, cont_memsize, cont_compact},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -1424,7 +1456,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
static const rb_data_type_t fiber_data_type = {
"fiber",
- {fiber_mark, fiber_free, fiber_memsize,},
+ {fiber_mark, fiber_free, fiber_memsize, fiber_compact,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
diff --git a/proc.c b/proc.c
index de60a8cdb9..8372979638 100644
--- a/proc.c
+++ b/proc.c
@@ -64,7 +64,7 @@ block_mark(const struct rb_block *block)
RUBY_MARK_NO_PIN_UNLESS_NULL(captured->self);
RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)captured->code.val);
if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) {
- RUBY_MARK_UNLESS_NULL(VM_ENV_ENVVAL(captured->ep));
+ RUBY_MARK_NO_PIN_UNLESS_NULL(VM_ENV_ENVVAL(captured->ep));
}
}
break;
@@ -87,6 +87,9 @@ block_compact(struct rb_block *block)
struct rb_captured_block *captured = &block->as.captured;
captured->self = rb_gc_location(captured->self);
captured->code.val = rb_gc_location(captured->code.val);
+ if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) {
+ UPDATE_REFERENCE(captured->ep[VM_ENV_DATA_INDEX_ENV]);
+ }
}
break;
case block_type_symbol:
diff --git a/variable.c b/variable.c
index ebfdf0dcce..be0eee1df3 100644
--- a/variable.c
+++ b/variable.c
@@ -1913,13 +1913,23 @@ static const rb_data_type_t autoload_data_i_type = {
};
static void
+autoload_c_compact(void *ptr)
+{
+ struct autoload_const *ac = ptr;
+
+ ac->mod = rb_gc_location(ac->mod);
+ ac->ad = rb_gc_location(ac->ad);
+ ac->value = rb_gc_location(ac->value);
+}
+
+static void
autoload_c_mark(void *ptr)
{
struct autoload_const *ac = ptr;
- rb_gc_mark(ac->mod);
- rb_gc_mark(ac->ad);
- rb_gc_mark(ac->value);
+ rb_gc_mark_no_pin(ac->mod);
+ rb_gc_mark_no_pin(ac->ad);
+ rb_gc_mark_no_pin(ac->value);
}
static void
@@ -1938,7 +1948,7 @@ autoload_c_memsize(const void *ptr)
static const rb_data_type_t autoload_const_type = {
"autoload_const",
- {autoload_c_mark, autoload_c_free, autoload_c_memsize,},
+ {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
diff --git a/vm.c b/vm.c
index 70ec2315c1..ce8853bb7d 100644
--- a/vm.c
+++ b/vm.c
@@ -2476,6 +2476,36 @@ rb_thread_recycle_stack_release(VALUE *stack)
}
void
+rb_execution_context_update(const rb_execution_context_t *ec)
+{
+ /* update VM stack */
+ if (ec->vm_stack) {
+ rb_control_frame_t *cfp = ec->cfp;
+ rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
+
+ while (cfp != limit_cfp) {
+ const VALUE *ep = cfp->ep;
+ cfp->self = rb_gc_location(cfp->self);
+ cfp->iseq = (rb_iseq_t *)rb_gc_location((VALUE)cfp->iseq);
+ cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);
+
+ if (!VM_ENV_LOCAL_P(ep)) {
+ VALUE *prev_ep = (VALUE *)VM_ENV_PREV_EP(ep);
+ if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
+ prev_ep[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]);
+ }
+ }
+
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ }
+ }
+#if VM_CHECK_MODE > 0
+ void rb_ec_verify(const rb_execution_context_t *ec); /* cont.c */
+ rb_ec_verify(ec);
+#endif
+}
+
+void
rb_execution_context_mark(const rb_execution_context_t *ec)
{
#if VM_CHECK_MODE > 0
@@ -2495,14 +2525,14 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
while (cfp != limit_cfp) {
const VALUE *ep = cfp->ep;
VM_ASSERT(!!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) == vm_ep_in_heap_p_(ec, ep));
- rb_gc_mark(cfp->self);
- rb_gc_mark((VALUE)cfp->iseq);
- rb_gc_mark((VALUE)cfp->block_code);
+ rb_gc_mark_no_pin(cfp->self);
+ rb_gc_mark_no_pin((VALUE)cfp->iseq);
+ rb_gc_mark_no_pin((VALUE)cfp->block_code);
if (!VM_ENV_LOCAL_P(ep)) {
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
- rb_gc_mark(prev_ep[VM_ENV_DATA_INDEX_ENV]);
+ rb_gc_mark_no_pin(prev_ep[VM_ENV_DATA_INDEX_ENV]);
}
}
@@ -2529,10 +2559,22 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
}
void rb_fiber_mark_self(rb_fiber_t *fib);
+void rb_fiber_update_self(rb_fiber_t *fib);
void rb_threadptr_root_fiber_setup(rb_thread_t *th);
void rb_threadptr_root_fiber_release(rb_thread_t *th);
static void
+thread_compact(void *ptr)
+{
+ rb_thread_t *th = ptr;
+ rb_fiber_update_self(th->ec->fiber_ptr);
+
+ if (th->root_fiber) rb_fiber_update_self(th->root_fiber);
+
+ rb_execution_context_update(th->ec);
+}
+
+static void
thread_mark(void *ptr)
{
rb_thread_t *th = ptr;
@@ -2617,6 +2659,7 @@ const rb_data_type_t ruby_threadptr_data_type = {
thread_mark,
thread_free,
thread_memsize,
+ thread_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
diff --git a/vm_core.h b/vm_core.h
index 95cd2d87d9..a0f9388df7 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1815,6 +1815,7 @@ void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th);
void rb_threadptr_pending_interrupt_clear(rb_thread_t *th);
void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v);
void rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo);
+void rb_execution_context_update(const rb_execution_context_t *ec);
void rb_execution_context_mark(const rb_execution_context_t *ec);
void rb_fiber_close(rb_fiber_t *fib);
void Init_native_thread(rb_thread_t *th);