1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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.
This commit is contained in:
Aaron Patterson 2020-05-07 10:07:57 -07:00
parent 7ded8fd29a
commit ff4f9cf95d
No known key found for this signature in database
GPG key ID: 953170BCB4FFAFC6
3 changed files with 45 additions and 1 deletions

1
gc.c
View file

@ -8491,6 +8491,7 @@ gc_update_references(rb_objspace_t * objspace)
objspace_each_objects_without_setup(objspace, gc_ref_update, objspace); objspace_each_objects_without_setup(objspace, gc_ref_update, objspace);
rb_vm_update_references(vm); rb_vm_update_references(vm);
rb_transient_heap_update_references(); rb_transient_heap_update_references();
rb_gc_update_global_tbl();
global_symbols.ids = rb_gc_location(global_symbols.ids); global_symbols.ids = rb_gc_location(global_symbols.ids);
global_symbols.dsymbol_fstr_hash = rb_gc_location(global_symbols.dsymbol_fstr_hash); global_symbols.dsymbol_fstr_hash = rb_gc_location(global_symbols.dsymbol_fstr_hash);
gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl); gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl);

View file

@ -28,6 +28,7 @@ struct rb_global_entry {
/* variable.c */ /* variable.c */
void rb_gc_mark_global_tbl(void); void rb_gc_mark_global_tbl(void);
void rb_gc_update_global_tbl(void);
size_t rb_generic_ivar_memsize(VALUE); size_t rb_generic_ivar_memsize(VALUE);
VALUE rb_search_class_path(VALUE); VALUE rb_search_class_path(VALUE);
VALUE rb_attr_delete(VALUE, ID); VALUE rb_attr_delete(VALUE, ID);

View file

@ -36,6 +36,8 @@
#include "variable.h" #include "variable.h"
#include "vm_core.h" #include "vm_core.h"
typedef void rb_gvar_compact_t(void *var);
static struct rb_id_table *rb_global_tbl; static struct rb_id_table *rb_global_tbl;
static ID autoload, classpath, tmp_classpath; static ID autoload, classpath, tmp_classpath;
static VALUE autoload_featuremap; /* feature => autoload_i */ static VALUE autoload_featuremap; /* feature => autoload_i */
@ -316,6 +318,7 @@ struct rb_global_variable {
rb_gvar_getter_t *getter; rb_gvar_getter_t *getter;
rb_gvar_setter_t *setter; rb_gvar_setter_t *setter;
rb_gvar_marker_t *marker; rb_gvar_marker_t *marker;
rb_gvar_compact_t *compactor;
struct trace_var *trace; struct trace_var *trace;
}; };
@ -333,6 +336,11 @@ rb_find_global_entry(ID id)
return entry; return entry;
} }
static void
rb_gvar_undef_compactor(void *var)
{
}
MJIT_FUNC_EXPORTED struct rb_global_entry* MJIT_FUNC_EXPORTED struct rb_global_entry*
rb_global_entry(ID id) rb_global_entry(ID id)
{ {
@ -348,6 +356,7 @@ rb_global_entry(ID id)
var->getter = rb_gvar_undef_getter; var->getter = rb_gvar_undef_getter;
var->setter = rb_gvar_undef_setter; var->setter = rb_gvar_undef_setter;
var->marker = rb_gvar_undef_marker; var->marker = rb_gvar_undef_marker;
var->compactor = rb_gvar_undef_compactor;
var->block_trace = 0; var->block_trace = 0;
var->trace = 0; var->trace = 0;
@ -364,6 +373,21 @@ rb_gvar_undef_getter(ID id, VALUE *_)
return Qnil; 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 void
rb_gvar_undef_setter(VALUE val, ID id, VALUE *_) 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->getter = rb_gvar_val_getter;
var->setter = rb_gvar_val_setter; var->setter = rb_gvar_val_setter;
var->marker = rb_gvar_val_marker; var->marker = rb_gvar_val_marker;
var->compactor = rb_gvar_val_compactor;
var->data = (void*)val; var->data = (void*)val;
} }
@ -397,7 +422,7 @@ void
rb_gvar_val_marker(VALUE *var) rb_gvar_val_marker(VALUE *var)
{ {
VALUE data = (VALUE)var; VALUE data = (VALUE)var;
if (data) rb_gc_mark(data); if (data) rb_gc_mark_movable(data);
} }
VALUE VALUE
@ -448,6 +473,23 @@ rb_gc_mark_global_tbl(void)
rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0); 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 static ID
global_id(const char *name) global_id(const char *name)
{ {