aboutsummaryrefslogtreecommitdiffstats
path: root/variable.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2020-05-07 10:07:57 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2020-05-07 11:42:39 -0700
commitff4f9cf95d73cc2730949df583bf0e41702d7aae (patch)
tree42101ad25cc3eb8d91ddc21162262812c41dc7b3 /variable.c
parent7ded8fd29a9dc5c481cadff7e94079009bce9e6c (diff)
downloadruby-ff4f9cf95d73cc2730949df583bf0e41702d7aae.tar.gz
Allow global variables to move
This patch allows global variables that have been assigned in Ruby to move. I added a new function for the GC to call that will update global references and introduced a new callback in the global variable struct for updating references. Only pure Ruby global variables are supported right now, other references will be pinned.
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/variable.c b/variable.c
index 3bcee434da..dad20f2f7b 100644
--- a/variable.c
+++ b/variable.c
@@ -36,6 +36,8 @@
#include "variable.h"
#include "vm_core.h"
+typedef void rb_gvar_compact_t(void *var);
+
static struct rb_id_table *rb_global_tbl;
static ID autoload, classpath, tmp_classpath;
static VALUE autoload_featuremap; /* feature => autoload_i */
@@ -316,6 +318,7 @@ struct rb_global_variable {
rb_gvar_getter_t *getter;
rb_gvar_setter_t *setter;
rb_gvar_marker_t *marker;
+ rb_gvar_compact_t *compactor;
struct trace_var *trace;
};
@@ -333,6 +336,11 @@ rb_find_global_entry(ID id)
return entry;
}
+static void
+rb_gvar_undef_compactor(void *var)
+{
+}
+
MJIT_FUNC_EXPORTED struct rb_global_entry*
rb_global_entry(ID id)
{
@@ -348,6 +356,7 @@ rb_global_entry(ID id)
var->getter = rb_gvar_undef_getter;
var->setter = rb_gvar_undef_setter;
var->marker = rb_gvar_undef_marker;
+ var->compactor = rb_gvar_undef_compactor;
var->block_trace = 0;
var->trace = 0;
@@ -364,6 +373,21 @@ rb_gvar_undef_getter(ID id, VALUE *_)
return Qnil;
}
+static void
+rb_gvar_val_compactor(void *_var)
+{
+ struct rb_global_variable *var = (struct rb_global_variable *)_var;
+
+ VALUE obj = (VALUE)var->data;
+
+ if (obj) {
+ VALUE new = rb_gc_location(obj);
+ if (new != obj) {
+ var->data = (void*)new;
+ }
+ }
+}
+
void
rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
{
@@ -371,6 +395,7 @@ rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
var->getter = rb_gvar_val_getter;
var->setter = rb_gvar_val_setter;
var->marker = rb_gvar_val_marker;
+ var->compactor = rb_gvar_val_compactor;
var->data = (void*)val;
}
@@ -397,7 +422,7 @@ void
rb_gvar_val_marker(VALUE *var)
{
VALUE data = (VALUE)var;
- if (data) rb_gc_mark(data);
+ if (data) rb_gc_mark_movable(data);
}
VALUE
@@ -448,6 +473,23 @@ rb_gc_mark_global_tbl(void)
rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
}
+static enum rb_id_table_iterator_result
+update_global_entry(VALUE v, void *ignored)
+{
+ struct rb_global_entry *entry = (struct rb_global_entry *)v;
+ struct rb_global_variable *var = entry->var;
+
+ (*var->compactor)(var);
+ return ID_TABLE_CONTINUE;
+}
+
+void
+rb_gc_update_global_tbl(void)
+{
+ if (rb_global_tbl)
+ rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
+}
+
static ID
global_id(const char *name)
{