summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorSatoshi Tagomori <[email protected]>2025-04-30 13:48:02 +0900
committerSatoshi Tagomori <[email protected]>2025-05-11 23:32:50 +0900
commit382645d440d5da66a0c04557f3ff2ca226de3a27 ()
treeb7453449930197237e739d0985561b664f51b0f3 /variable.c
parent49742414f6444960838bb968bab43db27f5872c1 (diff)
namespace on read
-rw-r--r--variable.c263
1 files changed, 228 insertions, 35 deletions
@@ -25,6 +25,7 @@
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
#include "internal/object.h"
#include "internal/gc.h"
#include "internal/re.h"
@@ -109,10 +110,10 @@ classname(VALUE klass, bool *permanent)
{
*permanent = false;
- VALUE classpath = RCLASS_EXT(klass)->classpath;
if (classpath == 0) return Qnil;
- *permanent = RCLASS_EXT(klass)->permanent_classpath;
return classpath;
}
@@ -210,7 +211,7 @@ static enum rb_id_table_iterator_result
set_sub_temporary_name_i(ID id, VALUE val, void *data)
{
val = ((rb_const_entry_t *)val)->value;
- if (rb_namespace_p(val) && !RCLASS_EXT(val)->permanent_classpath) {
VALUE arg = (VALUE)data;
struct sub_temporary_name_args *args = data;
args->last = id;
@@ -222,7 +223,7 @@ set_sub_temporary_name_i(ID id, VALUE val, void *data)
static void
set_sub_temporary_name_foreach(VALUE mod, struct sub_temporary_name_args *args, VALUE name)
{
- RCLASS_SET_CLASSPATH(mod, name, FALSE);
struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
if (!tbl) return;
if (!name) {
@@ -296,7 +297,7 @@ VALUE
rb_mod_set_temporary_name(VALUE mod, VALUE name)
{
// We don't allow setting the name if the classpath is already permanent:
- if (RCLASS_EXT(mod)->permanent_classpath) {
rb_raise(rb_eRuntimeError, "can't change permanent name");
}
@@ -529,6 +530,7 @@ struct rb_global_variable {
rb_gvar_marker_t *marker;
rb_gvar_compact_t *compactor;
struct trace_var *trace;
};
struct rb_global_entry {
@@ -604,6 +606,13 @@ rb_gvar_ractor_local(const char *name)
entry->ractor_local = true;
}
static void
rb_gvar_undef_compactor(void *var)
{
@@ -629,6 +638,7 @@ rb_global_entry(ID id)
var->block_trace = 0;
var->trace = 0;
rb_id_table_insert(rb_global_tbl, id, (VALUE)entry);
}
return entry;
@@ -982,13 +992,27 @@ rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val)
return val;
}
VALUE
rb_gvar_set(ID id, VALUE val)
{
struct rb_global_entry *entry;
entry = rb_global_entry(id);
- return rb_gvar_set_entry(entry, val);
}
VALUE
@@ -1000,9 +1024,27 @@ rb_gv_set(const char *name, VALUE val)
VALUE
rb_gvar_get(ID id)
{
struct rb_global_entry *entry = rb_global_entry(id);
struct rb_global_variable *var = entry->var;
- return (*var->getter)(entry->id, var->data);
}
VALUE
@@ -1056,6 +1098,7 @@ rb_f_global_variables(void)
if (!rb_ractor_main_p()) {
rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
}
rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary);
if (!NIL_P(backref)) {
@@ -1335,7 +1378,7 @@ rb_obj_field_get(VALUE obj, rb_shape_t *target_shape)
case T_CLASS:
case T_MODULE:
ASSERT_vm_locking();
- fields = RCLASS_FIELDS(obj);
break;
case T_OBJECT:
fields = ROBJECT_FIELDS(obj);
@@ -1392,7 +1435,7 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
found = rb_shape_get_iv_index(shape, id, &index);
if (found) {
- ivar_list = RCLASS_FIELDS(obj);
RUBY_ASSERT(ivar_list);
val = ivar_list[index];
@@ -1501,7 +1544,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
case T_MODULE:
- table = RCLASS_FIELDS_HASH(obj);
break;
case T_OBJECT:
@@ -1551,7 +1594,7 @@ obj_transition_too_complex(VALUE obj, st_table *table)
break;
case T_CLASS:
case T_MODULE:
- old_fields = RCLASS_FIELDS(obj);
rb_shape_set_shape_id(obj, shape_id);
RCLASS_SET_FIELDS_HASH(obj, table);
break;
@@ -2124,7 +2167,7 @@ rb_ivar_defined(VALUE obj, ID id)
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
case T_MODULE:
- table = (st_table *)RCLASS_FIELDS(obj);
break;
case T_OBJECT:
@@ -2188,7 +2231,8 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu
break;
case T_CLASS:
case T_MODULE:
- iv_list = RCLASS_FIELDS(itr_data->obj);
break;
default:
iv_list = itr_data->fields_tbl->as.shape.fields;
@@ -2280,7 +2324,7 @@ class_fields_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
};
if (rb_shape_obj_too_complex_p(obj)) {
- rb_st_foreach(RCLASS_FIELDS_HASH(obj), each_hash_iv, (st_data_t)&itr_data);
}
else {
iterate_over_shapes_with_callback(shape, func, &itr_data);
@@ -2701,7 +2745,7 @@ autoload_data(VALUE mod, ID id)
// If we are called with a non-origin ICLASS, fetch the autoload data from
// the original module.
if (RB_TYPE_P(mod, T_ICLASS)) {
- if (FL_TEST_RAW(mod, RICLASS_IS_ORIGIN)) {
return 0;
}
else {
@@ -2729,6 +2773,10 @@ struct autoload_const {
// The shared "autoload_data" if multiple constants are defined from the same feature.
VALUE autoload_data_value;
// The module we are loading a constant into.
VALUE module;
@@ -2866,6 +2914,70 @@ get_autoload_data(VALUE autoload_const_value, struct autoload_const **autoload_c
return autoload_data;
}
void
rb_autoload(VALUE module, ID name, const char *feature)
{
@@ -2883,6 +2995,7 @@ struct autoload_arguments {
VALUE module;
ID name;
VALUE feature;
};
static VALUE
@@ -2952,6 +3065,7 @@ autoload_synchronized(VALUE _arguments)
{
struct autoload_const *autoload_const;
VALUE autoload_const_value = TypedData_Make_Struct(0, struct autoload_const, &autoload_const_type, autoload_const);
autoload_const->module = arguments->module;
autoload_const->name = arguments->name;
autoload_const->value = Qundef;
@@ -2968,6 +3082,9 @@ autoload_synchronized(VALUE _arguments)
void
rb_autoload_str(VALUE module, ID name, VALUE feature)
{
if (!rb_is_const_id(name)) {
rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"", QUOTE_ID(name));
}
@@ -2981,6 +3098,7 @@ rb_autoload_str(VALUE module, ID name, VALUE feature)
.module = module,
.name = name,
.feature = feature,
};
VALUE result = rb_mutex_synchronize(autoload_mutex, autoload_synchronized, (VALUE)&arguments);
@@ -3241,22 +3359,82 @@ autoload_apply_constants(VALUE _arguments)
return Qtrue;
}
static VALUE
autoload_feature_require(VALUE _arguments)
{
struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments;
struct autoload_const *autoload_const = arguments->autoload_const;
// We save this for later use in autoload_apply_constants:
arguments->autoload_data = rb_check_typeddata(autoload_const->autoload_data_value, &autoload_data_type);
- VALUE result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1, arguments->autoload_data->feature);
if (RTEST(result)) {
return rb_mutex_synchronize(autoload_mutex, autoload_apply_constants, _arguments);
}
-
return result;
}
@@ -3580,6 +3758,8 @@ rb_mod_remove_const(VALUE mod, VALUE name)
return rb_const_remove(mod, id);
}
VALUE
rb_const_remove(VALUE mod, ID id)
{
@@ -3589,7 +3769,7 @@ rb_const_remove(VALUE mod, ID id)
rb_check_frozen(mod);
ce = rb_const_lookup(mod, id);
- if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
if (rb_const_defined_at(mod, id)) {
rb_name_err_raise("cannot remove %2$s::%1$s", mod, ID2SYM(id));
}
@@ -3607,7 +3787,11 @@ rb_const_remove(VALUE mod, ID id)
val = Qnil;
}
- ruby_xfree(ce);
return val;
}
@@ -3829,8 +4013,8 @@ set_namespace_path_i(ID id, VALUE v, void *payload)
}
set_namespace_path(value, build_const_path(parental_path, id));
- if (!RCLASS_EXT(value)->permanent_classpath) {
- RCLASS_SET_CLASSPATH(value, 0, false);
}
return ID_TABLE_CONTINUE;
@@ -3848,7 +4032,7 @@ set_namespace_path(VALUE named_namespace, VALUE namespace_path)
RB_VM_LOCK_ENTER();
{
- RCLASS_SET_CLASSPATH(named_namespace, namespace_path, true);
if (const_table) {
rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
@@ -3884,9 +4068,10 @@ const_set(VALUE klass, ID id, VALUE val)
RB_VM_LOCK_ENTER();
{
- struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
if (!tbl) {
- RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
rb_clear_constant_cache_for_id(id);
ce = ZALLOC(rb_const_entry_t);
rb_id_table_insert(tbl, id, (VALUE)ce);
@@ -4010,6 +4195,7 @@ const_tbl_update(struct autoload_const *ac, int autoload_force)
setup_const_entry(ce, klass, val, visibility);
}
else {
rb_clear_constant_cache_for_id(id);
ce = ZALLOC(rb_const_entry_t);
@@ -4172,7 +4358,7 @@ static int
cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
{
if (RB_TYPE_P(klass, T_ICLASS)) {
- if (FL_TEST_RAW(klass, RICLASS_IS_ORIGIN)) {
return 0;
}
else {
@@ -4277,10 +4463,11 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
int result = rb_class_ivar_set(target, id, val);
- struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
if (!rb_cvc_tbl) {
- rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
}
struct rb_cvar_class_tbl_entry *ent;
@@ -4304,7 +4491,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
// cvar in this lookup.
if (result == 0) {
if (RB_TYPE_P(target, T_CLASS)) {
- if (RCLASS_SUBCLASSES(target)) {
rb_class_foreach_subclass(target, check_for_cvar_table, id);
}
}
@@ -4538,13 +4725,13 @@ class_ivar_set_shape_fields(VALUE obj, void *_data)
{
RUBY_ASSERT(!rb_shape_obj_too_complex_p(obj));
- return RCLASS_FIELDS(obj);
}
static void
class_ivar_set_shape_resize_fields(VALUE obj, attr_index_t _old_capa, attr_index_t new_capa, void *_data)
{
- REALLOC_N(RCLASS_FIELDS(obj), VALUE, new_capa);
}
static void
@@ -4564,7 +4751,7 @@ class_ivar_set_too_complex_table(VALUE obj, void *_data)
{
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
- return RCLASS_FIELDS_HASH(obj);
}
int
@@ -4574,6 +4761,8 @@ rb_class_ivar_set(VALUE obj, ID id, VALUE val)
bool existing = false;
rb_check_frozen(obj);
RB_VM_LOCK_ENTER();
{
existing = general_ivar_set(obj, id, val, NULL,
@@ -4620,11 +4809,9 @@ rb_fields_tbl_copy(VALUE dst, VALUE src)
rb_ivar_foreach(src, tbl_copy_i, dst);
}
-rb_const_entry_t *
-rb_const_lookup(VALUE klass, ID id)
{
- struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
-
if (tbl) {
VALUE val;
bool r;
@@ -4638,3 +4825,9 @@ rb_const_lookup(VALUE klass, ID id)
}
return NULL;
}