aboutsummaryrefslogtreecommitdiffstats
path: root/proc.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2019-05-30 12:08:06 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2019-06-03 13:38:47 -0700
commit4eb1c2365cd2745b58eb835ea1e26cc33a1238b1 (patch)
tree47a211a45ecd62bddefa328081965f76e48fec6c /proc.c
parentca22cccc14e17d21b4fe7b5aed680e9edf12afb7 (diff)
downloadruby-4eb1c2365cd2745b58eb835ea1e26cc33a1238b1.tar.gz
Unpin objects that `proc` references
This commit adds compaction support to method and proc objects. It just unpins references and implements the "compact" callback and updates references.
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c71
1 files changed, 62 insertions, 9 deletions
diff --git a/proc.c b/proc.c
index 5ac26be428..de60a8cdb9 100644
--- a/proc.c
+++ b/proc.c
@@ -25,6 +25,9 @@
# define NO_CLOBBERED(v) (v)
#endif
+#define UPDATE_TYPED_REFERENCE(_type, _ref) *(_type*)&_ref = (_type)rb_gc_location((VALUE)_ref)
+#define UPDATE_REFERENCE(_ref) UPDATE_TYPED_REFERENCE(VALUE, _ref)
+
const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
struct METHOD {
@@ -58,23 +61,51 @@ block_mark(const struct rb_block *block)
case block_type_ifunc:
{
const struct rb_captured_block *captured = &block->as.captured;
- RUBY_MARK_UNLESS_NULL(captured->self);
- RUBY_MARK_UNLESS_NULL((VALUE)captured->code.val);
+ 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));
}
}
break;
case block_type_symbol:
- RUBY_MARK_UNLESS_NULL(block->as.symbol);
+ RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.symbol);
+ break;
+ case block_type_proc:
+ RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.proc);
+ break;
+ }
+}
+
+static void
+block_compact(struct rb_block *block)
+{
+ switch (block->type) {
+ case block_type_iseq:
+ case block_type_ifunc:
+ {
+ struct rb_captured_block *captured = &block->as.captured;
+ captured->self = rb_gc_location(captured->self);
+ captured->code.val = rb_gc_location(captured->code.val);
+ }
+ break;
+ case block_type_symbol:
+ block->as.symbol = rb_gc_location(block->as.symbol);
break;
case block_type_proc:
- RUBY_MARK_UNLESS_NULL(block->as.proc);
+ block->as.proc = rb_gc_location(block->as.proc);
break;
}
}
static void
+proc_compact(void *ptr)
+{
+ rb_proc_t *proc = ptr;
+ block_compact((struct rb_block *)&proc->block);
+}
+
+static void
proc_mark(void *ptr)
{
rb_proc_t *proc = ptr;
@@ -102,6 +133,7 @@ static const rb_data_type_t proc_data_type = {
proc_mark,
RUBY_TYPED_DEFAULT_FREE,
proc_memsize,
+ proc_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
@@ -260,10 +292,19 @@ binding_mark(void *ptr)
RUBY_MARK_ENTER("binding");
block_mark(&bind->block);
- rb_gc_mark(bind->pathobj);
+ rb_gc_mark_no_pin(bind->pathobj);
RUBY_MARK_LEAVE("binding");
}
+static void
+binding_compact(void *ptr)
+{
+ rb_binding_t *bind = ptr;
+
+ block_compact((struct rb_block *)&bind->block);
+ UPDATE_REFERENCE(bind->pathobj);
+}
+
static size_t
binding_memsize(const void *ptr)
{
@@ -276,6 +317,7 @@ const rb_data_type_t ruby_binding_data_type = {
binding_mark,
binding_free,
binding_memsize,
+ binding_compact,
},
0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -1316,10 +1358,20 @@ static void
bm_mark(void *ptr)
{
struct METHOD *data = ptr;
- rb_gc_mark(data->recv);
- rb_gc_mark(data->klass);
- rb_gc_mark(data->iclass);
- rb_gc_mark((VALUE)data->me);
+ rb_gc_mark_no_pin(data->recv);
+ rb_gc_mark_no_pin(data->klass);
+ rb_gc_mark_no_pin(data->iclass);
+ rb_gc_mark_no_pin((VALUE)data->me);
+}
+
+static void
+bm_compact(void *ptr)
+{
+ struct METHOD *data = ptr;
+ UPDATE_REFERENCE(data->recv);
+ UPDATE_REFERENCE(data->klass);
+ UPDATE_REFERENCE(data->iclass);
+ UPDATE_TYPED_REFERENCE(rb_method_entry_t *, data->me);
}
static size_t
@@ -1334,6 +1386,7 @@ static const rb_data_type_t method_data_type = {
bm_mark,
RUBY_TYPED_DEFAULT_FREE,
bm_memsize,
+ bm_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};