14#include "ruby/internal/config.h"
17#include "ccan/list/list.h"
19#include "debug_counter.h"
23#include "internal/box.h"
24#include "internal/class.h"
25#include "internal/compilers.h"
26#include "internal/error.h"
27#include "internal/eval.h"
28#include "eval_intern.h"
29#include "internal/hash.h"
30#include "internal/object.h"
31#include "internal/gc.h"
32#include "internal/ractor.h"
33#include "internal/re.h"
34#include "internal/string.h"
35#include "internal/struct.h"
36#include "internal/symbol.h"
37#include "internal/thread.h"
38#include "internal/variable.h"
39#include "internal/vm.h"
47#include "ractor_core.h"
51#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
53typedef void rb_gvar_compact_t(
void *var);
60static VALUE autoload_features;
65static VALUE autoload_mutex;
67static void check_before_mod_set(
VALUE,
ID,
VALUE,
const char *);
69static VALUE rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility,
VALUE *found_in);
78typedef int rb_ivar_foreach_callback_func(
ID key,
VALUE val, st_data_t arg);
79static void rb_field_foreach(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only);
82rb_generic_fields_lock_atfork(
void)
91 rb_global_tbl = rb_id_table_create(0);
92 generic_fields_tbl_ = st_init_numtable();
96 rb_vm_register_global_object(autoload_mutex);
98 autoload_features = rb_ident_hash_new();
100 rb_vm_register_global_object(autoload_features);
104rb_namespace_p(
VALUE obj)
125classname(
VALUE klass,
bool *permanent)
129 VALUE classpath = RCLASS_CLASSPATH(klass);
130 if (classpath == 0)
return Qnil;
132 *permanent = RCLASS_PERMANENT_CLASSPATH_P(klass);
138rb_mod_name0(
VALUE klass,
bool *permanent)
140 return classname(klass, permanent);
155 return classname(mod, &permanent);
160is_constant_path(
VALUE name)
162 const char *path = RSTRING_PTR(name);
166 const char *p = path;
168 if (p >= pend || !*p) {
173 if (p + 2 <= pend && p[0] ==
':' && p[1] ==
':') {
177 const char *pbeg = p;
178 while (p < pend && *p !=
':') p++;
180 if (pbeg == p)
return false;
182 if (rb_enc_symname_type(pbeg, p - pbeg, enc, 0) != ID_CONST) {
199set_sub_temporary_name_recursive(
VALUE mod,
VALUE data,
int recursive)
201 if (recursive)
return Qfalse;
206 name = build_const_path(rb_ary_last(0, 0, args->names), args->last);
208 set_sub_temporary_name_foreach(mod, args, name);
213set_sub_temporary_name_topmost(
VALUE mod,
VALUE data,
int recursive)
215 if (recursive)
return Qfalse;
218 VALUE name = args->names;
222 set_sub_temporary_name_foreach(mod, args, name);
226static enum rb_id_table_iterator_result
227set_sub_temporary_name_i(
ID id,
VALUE val,
void *data)
230 if (rb_namespace_p(val) && !RCLASS_PERMANENT_CLASSPATH_P(val)) {
236 return ID_TABLE_CONTINUE;
242 RCLASS_WRITE_CLASSPATH(mod, name, FALSE);
246 rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
251 rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
252 rb_ary_set_len(args->names, names_len);
313rb_mod_set_temporary_name(
VALUE mod,
VALUE name)
315 rb_class_owner_check(mod);
318 if (RCLASS_PERMANENT_CLASSPATH_P(mod)) {
325 set_sub_temporary_name(mod, 0);
332 if (RSTRING_LEN(name) == 0) {
333 rb_raise(rb_eArgError,
"empty class/module name");
336 if (is_constant_path(name)) {
337 rb_raise(rb_eArgError,
"the temporary name must not be a constant path to avoid confusion");
345 set_sub_temporary_name(mod, name);
358 path = rb_sprintf(
"#<Class:%p>", (
void*)obj);
361 path = rb_sprintf(
"#<Module:%p>", (
void*)obj);
364 path = rb_sprintf(
"#<%"PRIsVALUE
":%p>", klass, (
void*)obj);
374rb_tmp_class_path(
VALUE klass,
bool *permanent, fallback_func fallback)
376 VALUE path = classname(klass, permanent);
388 path = rb_tmp_class_path(
RBASIC(klass)->klass, &perm, fallback);
393 return fallback(klass, path);
400 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
418rb_search_class_path(
VALUE klass)
421 return rb_tmp_class_path(klass, &permanent, no_fallback);
430 return rb_fstring(path);
434build_const_path(
VALUE head,
ID tail)
436 return build_const_pathname(head, rb_id2str(tail));
442 bool permanent =
true;
449 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
450 str = build_const_pathname(str, name);
454 RCLASS_SET_CLASSPATH(klass, str, permanent);
469 const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
473 if (!rb_enc_asciicompat(enc)) {
474 rb_raise(rb_eArgError,
"invalid class path encoding (non ASCII)");
477 pend = path + RSTRING_LEN(pathname);
478 if (path == pend || path[0] ==
'#') {
479 rb_raise(rb_eArgError,
"can't retrieve anonymous class %"PRIsVALUE,
483 while (p < pend && *p !=
':') p++;
485 if (p < pend && p[0] ==
':') {
486 if ((
size_t)(pend - p) < 2 || p[1] !=
':')
goto undefined_class;
491 goto undefined_class;
493 c = rb_const_search(c,
id, TRUE, FALSE, FALSE, NULL);
494 if (UNDEF_P(c))
goto undefined_class;
495 if (!rb_namespace_p(c)) {
496 rb_raise(
rb_eTypeError,
"%"PRIsVALUE
" does not refer to class/module",
505 rb_raise(rb_eArgError,
"undefined class/module % "PRIsVALUE,
526 VALUE path = rb_tmp_class_path(
rb_class_real(klass), &permanent, make_temporary_path);
527 if (
NIL_P(path))
return NULL;
528 return RSTRING_PTR(path);
551 rb_gvar_compact_t *compactor;
578static enum rb_id_table_iterator_result
579free_global_entry_i(
VALUE val,
void *arg)
582 entry->var->counter--;
583 if (entry->var->counter == 0) {
584 free_global_variable(entry->var);
587 return ID_TABLE_DELETE;
591rb_free_rb_global_tbl(
void)
593 rb_id_table_foreach_values(rb_global_tbl, free_global_entry_i, 0);
594 rb_id_table_free(rb_global_tbl);
598rb_free_generic_fields_tbl_(
void)
600 st_free_table(generic_fields_tbl_);
604rb_gvar_undef_compactor(
void *var)
608NORETURN(
static void global_entry_isolation_error(
ID id));
611global_entry_isolation_error(
ID id)
613 rb_raise(rb_eRactorIsolationError,
"can not access global variable %s from non-main Ractor", rb_id2name(
id));
619global_entry_lookup(
ID id,
bool create_entry,
bool *isolation_error)
625 if (rb_id_table_lookup(rb_global_tbl,
id, &data)) {
633 *isolation_error = UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local);
635 if (!entry && create_entry && !*isolation_error) {
640 entry->ractor_local =
false;
647 var->compactor = rb_gvar_undef_compactor;
649 var->block_trace = 0;
651 var->box_ready =
false;
652 var->box_dynamic =
false;
653 rb_id_table_insert(rb_global_tbl,
id, (
VALUE)entry);
661rb_find_global_entry(
ID id)
663 bool isolation_error;
664 struct rb_global_entry *entry = global_entry_lookup(
id,
false, &isolation_error);
666 if (isolation_error) global_entry_isolation_error(
id);
672rb_gvar_ractor_local(
const char *name)
675 entry->ractor_local =
true;
679rb_gvar_box_ready(
const char *name)
682 entry->var->box_ready =
true;
686rb_gvar_box_dynamic(
const char *name)
689 entry->var->box_dynamic =
true;
695 bool isolation_error;
696 struct rb_global_entry *entry = global_entry_lookup(
id,
true, &isolation_error);
698 if (isolation_error) global_entry_isolation_error(
id);
706 rb_warning(
"global variable '%"PRIsVALUE
"' not initialized", QUOTE_ID(
id));
712rb_gvar_val_compactor(
void *_var)
717 rb_gc_update_moved_ptr(&var->data);
728 var->compactor = rb_gvar_val_compactor;
730 var->data = (
void*)val;
748 var->data = (
void*)val;
755 if (data) rb_gc_mark_movable(data);
761 if (!var)
return Qnil;
774 if (var) rb_gc_mark_maybe(*var);
780 rb_name_error(
id,
"%"PRIsVALUE
" is a read-only variable", QUOTE_ID(
id));
783static enum rb_id_table_iterator_result
784mark_global_entry(
VALUE v,
void *ignored)
790 (*var->marker)(var->data);
793 if (trace->data) rb_gc_mark_maybe(trace->data);
796 return ID_TABLE_CONTINUE;
799#define gc_mark_table(task) \
800 if (rb_global_tbl) { rb_id_table_foreach_values(rb_global_tbl, task##_global_entry, 0); }
803rb_gc_mark_global_tbl(
void)
808static enum rb_id_table_iterator_result
809update_global_entry(
VALUE v,
void *ignored)
814 (*var->compactor)(var);
815 return ID_TABLE_CONTINUE;
819rb_gc_update_global_tbl(
void)
821 gc_mark_table(update);
825global_id(
const char *name)
829 if (name[0] ==
'$')
id = rb_intern(name);
831 size_t len = strlen(name);
835 memcpy(buf+1, name,
len);
836 id = rb_intern2(buf,
len+1);
843find_global_id(
const char *name)
846 size_t len = strlen(name);
848 if (name[0] ==
'$') {
855 memcpy(buf+1, name,
len);
871 ID id = global_id(name);
874 gvar->data = (
void*)var;
926 trace->next = entry->var->trace;
927 trace->func = rb_trace_eval;
930 entry->var->trace = trace;
944 while (trace->next) {
947 trace->next = next->next;
970 if ((entry = rb_find_global_entry(
id)) == NULL) {
971 rb_name_error(
id,
"undefined global variable %"PRIsVALUE
"", QUOTE_ID(
id));
974 trace = entry->var->trace;
985 if (!entry->var->block_trace) remove_trace(entry->var);
990 if (trace->data == cmd) {
992 if (!entry->var->block_trace) remove_trace(entry->var);
1013 (*trace->func)(trace->data, data->val);
1014 trace = trace->next;
1024 var->block_trace = 0;
1034 if (var->trace && !var->block_trace) {
1035 var->block_trace = 1;
1036 trace.trace = var->trace;
1047 (*var->setter)(val, entry->id, var->data);
1048 gvar_trace(var, val);
1055 return BOX_USER_P(box) &&
1056 !entry->var->box_dynamic &&
1065 const rb_box_t *box = rb_current_box();
1066 bool use_box_tbl =
false;
1067 bool isolation_error =
false;
1070 entry = global_entry_lookup(
id,
true, &isolation_error);
1072 if (!isolation_error && gvar_use_box_tbl(box, entry)) {
1074 rb_hash_aset(box->gvar_tbl,
rb_id2sym(entry->var->id), val);
1079 if (isolation_error) global_entry_isolation_error(
id);
1082 gvar_trace(entry->var, val);
1085 retval = rb_gvar_set_entry(entry, val);
1093 return rb_gvar_set(global_id(name), val);
1099 VALUE retval, gvars, key;
1100 const rb_box_t *box = rb_current_box();
1101 bool use_box_tbl =
false;
1102 bool isolation_error =
false;
1108 entry = global_entry_lookup(
id,
true, &isolation_error);
1110 if (!isolation_error) {
1113 if (gvar_use_box_tbl(box, entry)) {
1115 gvars = box->gvar_tbl;
1117 if (
RTEST(rb_hash_has_key(gvars, key))) {
1118 retval = rb_hash_aref(gvars, key);
1126 retval = (*var->getter)(entry->id, var->data);
1128 retval =
rb_funcall(retval, rb_intern(
"clone"), 0);
1132 if (cache) rb_hash_aset(gvars, key, retval);
1138 if (isolation_error) global_entry_isolation_error(
id);
1141 retval = (*var->getter)(entry->id, var->data);
1149 ID id = find_global_id(name);
1152 rb_warning(
"global variable '%s' not initialized", name);
1156 return rb_gvar_get(
id);
1160rb_gvar_defined(
ID id)
1162 const rb_box_t *box = rb_current_box();
1169 (gvar_use_box_tbl(box, entry) &&
1170 RTEST(rb_hash_has_key(box->gvar_tbl,
rb_id2sym(entry->var->id))));
1172 return RBOOL(defined);
1176rb_gvar_getter_function_of(
ID id)
1179 return entry->var->getter;
1183rb_gvar_setter_function_of(
ID id)
1186 return entry->var->setter;
1189static enum rb_id_table_iterator_result
1190gvar_i(
ID key,
VALUE val,
void *a)
1194 return ID_TABLE_CONTINUE;
1203 if (!rb_ractor_main_p()) {
1204 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
1208 rb_id_table_foreach(rb_global_tbl, gvar_i, (
void *)ary);
1209 if (!
NIL_P(backref)) {
1211 int i, nmatch = rb_match_count(backref);
1213 for (i = 1; i <= nmatch; ++i) {
1217 buf[1] = (char)(i +
'0');
1218 sym =
ID2SYM(rb_intern2(buf, 2));
1236 bool tracer_error =
false;
1238 if (!rb_ractor_main_p()) {
1239 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
1243 bool isolation_error;
1244 entry2 = global_entry_lookup(name2,
true, &isolation_error);
1245 VM_ASSERT(!isolation_error);
1247 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
1250 rb_id_table_insert(gtbl, name1, (
VALUE)entry1);
1252 else if ((entry1 = (
struct rb_global_entry *)data1)->var != entry2->var) {
1254 if (var->block_trace) {
1255 tracer_error =
true;
1259 if (var->counter == 0) {
1260 free_global_variable(var);
1264 if (!tracer_error && entry1->var != entry2->var) {
1265 entry2->var->counter++;
1266 entry1->var = entry2->var;
1274class_ivar_set_ractor_check(
VALUE klass,
ID id)
1277 UNLIKELY(!rb_class_owned_p(klass))) {
1279 rb_eRactorIsolationError,
1280 "can not set instance variables of classes/modules "
1281 "created by another Ractor (%"PRIsVALUE
" from %"PRIsVALUE
")",
1291cvar_set_ractor_check(
VALUE klass,
ID id)
1293 if (UNLIKELY(!rb_class_owned_p(klass))) {
1294 rb_raise(rb_eRactorIsolationError,
1295 "can not set class variable %"PRIsVALUE
" of %"PRIsVALUE
", which was created by another Ractor",
1296 rb_id2str(
id), klass);
1303 if (UNLIKELY(!rb_class_owned_p(klass)) && !rb_class_field_shareable_p(klass, val)) {
1304 rb_raise(rb_eRactorIsolationError,
1305 "can not read non-shareable class variable %"PRIsVALUE
" of %"PRIsVALUE
", which was created by another Ractor",
1306 rb_id2str(
id), klass);
1311ivar_ractor_assert(
VALUE obj,
ID id)
1319 rb_shape_frozen_p(RBASIC_SHAPE_ID(obj)),
1320 "shareable object must not have writable instance variables");
1324rb_generic_fields_tbl_get(
void)
1326 return generic_fields_tbl_;
1335 if (rb_multi_ractor_p()) {
1343 if (rb_multi_ractor_p()) {
1349rb_mark_generic_ivar(
VALUE obj)
1354 if (rb_gc_during_global_gc_p() && rb_gc_multi_objspace_p()) {
1362 st_lookup(generic_fields_tbl_, (st_data_t)obj, (st_data_t *)&data);
1365 rb_gc_mark_movable(data);
1373rb_obj_fields_generic_uncached(
VALUE obj)
1375 VALUE fields_obj = 0;
1379 found = st_lookup(generic_fields_tbl_, (st_data_t)obj, (st_data_t *)&fields_obj);
1383 rb_bug(
"Object is missing entry in generic_fields_tbl");
1389obj_use_generic_fields_tbl_p(
VALUE obj)
1404rb_obj_fields(
VALUE obj,
ID field_name)
1406 ivar_ractor_assert(obj, field_name);
1414 return ROBJECT_FIELDS_OBJ(obj);
1418 return RCLASS_WRITABLE_FIELDS_OBJ(obj);
1421 return rbimpl_atomic_value_load(&
RTYPEDDATA(obj)->fields_obj, RBIMPL_ATOMIC_ACQUIRE);
1424 return RSTRUCT_FIELDS_OBJ(obj);
1428 VALUE fields_obj = 0;
1430 if (rb_obj_shape_has_fields(obj)) {
1432 if (ec->gen_fields_cache.obj == obj && !UNDEF_P(ec->gen_fields_cache.fields_obj) && rb_imemo_fields_owner(ec->gen_fields_cache.fields_obj) == obj) {
1433 fields_obj = ec->gen_fields_cache.fields_obj;
1434 RUBY_ASSERT(fields_obj == rb_obj_fields_generic_uncached(obj));
1437 fields_obj = rb_obj_fields_generic_uncached(obj);
1438 ec->gen_fields_cache.fields_obj = fields_obj;
1439 ec->gen_fields_cache.obj = obj;
1451 if (rb_obj_gen_fields_p(obj)) {
1452 st_data_t key = (st_data_t)obj, value;
1458 RSTRUCT_SET_FIELDS_OBJ(obj, 0);
1466 if (ec->gen_fields_cache.obj == obj) {
1467 ec->gen_fields_cache.obj =
Qundef;
1468 ec->gen_fields_cache.fields_obj =
Qundef;
1473 if (rb_gc_during_global_gc_p() || ruby_vm_during_cleanup) {
1481 deleted = st_delete(generic_fields_tbl_, &key, &value);
1484 rb_bug(
"Object is missing entry in generic_fields_tbl");
1488 RBASIC_SET_SHAPE_ID(obj, ROOT_SHAPE_ID);
1493rb_obj_set_fields(
VALUE obj,
VALUE fields_obj,
ID field_name,
VALUE original_fields_obj)
1495 ivar_ractor_assert(obj, field_name);
1500 rb_imemo_fields_clear(original_fields_obj);
1504 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
1508 if (fields_obj != original_fields_obj) {
1512 ROBJECT_SET_EXTENDED(obj, fields_obj);
1515 RB_OBJ_ATOMIC_WRITE(obj, &
RTYPEDDATA(obj)->fields_obj, fields_obj);
1518 RSTRUCT_SET_FIELDS_OBJ(obj, fields_obj);
1527 bool gc_disabled =
RTEST(rb_gc_local_disable_no_rest());
1529 enum ruby_tag_type state;
1531 EC_PUSH_TAG(insert_ec);
1532 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1533 st_insert(generic_fields_tbl_, (st_data_t)obj, (st_data_t)fields_obj);
1537 if (!gc_disabled) rb_gc_local_enable();
1538 if (state != TAG_NONE) EC_JUMP_TAG(insert_ec, state);
1542 if (ec->gen_fields_cache.fields_obj != fields_obj) {
1543 ec->gen_fields_cache.obj = obj;
1544 ec->gen_fields_cache.fields_obj = fields_obj;
1549 if (original_fields_obj && original_fields_obj != obj) {
1551 rb_imemo_fields_clear(original_fields_obj);
1556 RBASIC_SET_SHAPE_ID_WITH_LAYOUT(obj, RBASIC_SHAPE_ID(fields_obj), SHAPE_ID_LAYOUT_EXTENDED);
1559 RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(fields_obj));
1564rb_obj_replace_fields(
VALUE obj,
VALUE fields_obj)
1566 if (obj_use_generic_fields_tbl_p(obj)) {
1570 VALUE original_fields_obj = rb_obj_fields_no_ractor_check(obj);
1571 rb_obj_set_fields(obj, fields_obj, 0, original_fields_obj);
1575 VALUE original_fields_obj = rb_obj_fields_no_ractor_check(obj);
1576 rb_obj_set_fields(obj, fields_obj, 0, original_fields_obj);
1581rb_imemo_fields_field_get(
VALUE fields_obj, shape_id_t target_shape_id)
1583 RUBY_ASSERT(RSHAPE_TYPE_P(target_shape_id, SHAPE_IVAR) || RSHAPE_TYPE_P(target_shape_id, SHAPE_OBJ_ID));
1585 if (UNLIKELY(rb_shape_complex_p(target_shape_id))) {
1586 st_table *fields_hash = rb_imemo_fields_complex_tbl(fields_obj);
1588 st_lookup(fields_hash, RSHAPE_EDGE_NAME(target_shape_id), &value);
1593 attr_index_t index = RSHAPE_INDEX(target_shape_id);
1594 return rb_imemo_fields_ptr(fields_obj)[index];
1598rb_obj_field_get(
VALUE obj, shape_id_t target_shape_id)
1602 return rb_imemo_fields_field_get(rb_obj_fields(obj, RSHAPE_EDGE_NAME(target_shape_id)), target_shape_id);
1612 VALUE fields_obj = rb_obj_fields(obj, is_class ? 0 : id);
1618 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1621 if (UNLIKELY(rb_shape_complex_p(shape_id))) {
1622 st_table *iv_table = rb_imemo_fields_complex_tbl(fields_obj);
1623 if (!rb_st_lookup(iv_table, (st_data_t)
id, (st_data_t *)&val)) {
1628 attr_index_t index = 0;
1629 if (!rb_shape_get_iv_index(shape_id,
id, &index)) {
1632 val = rb_imemo_fields_ptr(fields_obj)[index];
1636 if (UNLIKELY(!rb_class_owned_p(obj)) && !rb_class_field_shareable_p(obj, val)) {
1638 rb_eRactorIsolationError,
1639 "can not get unshareable values from instance variables of classes/modules "
1640 "created by another Ractor (%"PRIsVALUE
" from %"PRIsVALUE
")",
1653 VALUE iv = rb_ivar_lookup(obj,
id,
Qnil);
1654 RB_DEBUG_COUNTER_INC(ivar_get_base);
1659rb_ivar_get_at(
VALUE obj, attr_index_t index,
ID id)
1670 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1671 VALUE val = rb_imemo_fields_ptr(fields_obj)[index];
1673 if (UNLIKELY(!rb_class_owned_p(obj)) && !rb_class_field_shareable_p(obj, val)) {
1675 rb_eRactorIsolationError,
1676 "can not get unshareable values from instance variables of classes/modules "
1677 "created by another Ractor (%"PRIsVALUE
" from %"PRIsVALUE
")",
1687 VALUE fields_obj = rb_obj_fields(obj,
id);
1688 return rb_imemo_fields_ptr(fields_obj)[index];
1694rb_ivar_get_at_no_ractor_check(
VALUE obj, attr_index_t index)
1698 VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
1699 return rb_imemo_fields_ptr(fields_obj)[index];
1705 return rb_ivar_lookup(obj,
id,
Qnil);
1708static VALUE imemo_fields_evacutate_to_complex(
VALUE owner,
VALUE source_fields_obj, shape_id_t shape_id,
int extra_capa);
1711rb_obj_convert_too_complex(
VALUE obj,
VALUE fields_obj, shape_id_t shape_id)
1716 shape_id = rb_shape_transition_complex(shape_id);
1717 VALUE new_fields_obj = imemo_fields_evacutate_to_complex(obj, fields_obj, shape_id, 1);
1718 ROBJECT_SET_EXTENDED(obj, new_fields_obj);
1719 RBASIC_SET_SHAPE_ID_WITH_LAYOUT(obj, shape_id, SHAPE_ID_LAYOUT_EXTENDED);
1726 rb_check_frozen(obj);
1729 bool concurrent =
false;
1733 class_ivar_set_ractor_check(obj,
id);
1735 if (rb_multi_ractor_p()) {
1740 VALUE fields_obj = rb_obj_fields(obj,
id);
1745 const VALUE original_fields_obj = fields_obj;
1747 fields_obj = rb_imemo_fields_clone(fields_obj);
1750 shape_id_t old_shape_id = RBASIC_SHAPE_ID(fields_obj);
1751 shape_id_t removed_shape_id;
1752 shape_id_t next_shape_id = rb_obj_shape_transition_remove_ivar(fields_obj,
id, &removed_shape_id);
1754 if (UNLIKELY(rb_shape_complex_p(next_shape_id))) {
1755 if (UNLIKELY(!rb_shape_complex_p(old_shape_id))) {
1756 fields_obj = imemo_fields_evacutate_to_complex(obj, fields_obj, next_shape_id, -1);
1759 if (!st_delete(rb_imemo_fields_complex_tbl(fields_obj), &key, (st_data_t *)&val)) {
1764 if (next_shape_id == old_shape_id) {
1768 RUBY_ASSERT(removed_shape_id != INVALID_SHAPE_ID);
1769 RUBY_ASSERT(RSHAPE_LEN(next_shape_id) == RSHAPE_LEN(old_shape_id) - 1);
1771 VALUE *fields = rb_imemo_fields_ptr(fields_obj);
1772 attr_index_t removed_index = RSHAPE_INDEX(removed_shape_id);
1773 val = fields[removed_index];
1775 attr_index_t new_fields_count = RSHAPE_LEN(next_shape_id);
1776 if (new_fields_count) {
1777 size_t trailing_fields = new_fields_count - removed_index;
1779 MEMMOVE(&fields[removed_index], &fields[removed_index + 1],
VALUE, trailing_fields);
1780 RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
1782 if (
type ==
T_OBJECT && obj != fields_obj && new_fields_count == rb_shape_embedded_capacity(RBASIC_SHAPE_ID(obj))) {
1787 VALUE *embedded_fields = ROBJECT_EMBEDDED_FIELDS(obj);
1788 MEMCPY(embedded_fields, fields,
VALUE, new_fields_count);
1789 for (attr_index_t i = 0; i < new_fields_count; i++) {
1801 if (fields_obj != original_fields_obj) {
1804 if (fields_obj && fields_obj != obj) {
1805 ROBJECT_SET_EXTENDED(obj, fields_obj);
1810 RCLASS_WRITABLE_SET_FIELDS_OBJ(obj, fields_obj);
1813 rb_obj_set_fields(obj, fields_obj,
id, original_fields_obj);
1819 if (!fields_obj || fields_obj == obj) {
1820 RBASIC_SET_SHAPE_ID_WITH_LAYOUT(obj, next_shape_id, SHAPE_ID_LAYOUT_ROBJECT);
1823 RBASIC_SET_SHAPE_ID_WITH_LAYOUT(obj, next_shape_id, SHAPE_ID_LAYOUT_EXTENDED);
1827 RBASIC_SET_SHAPE_ID(obj, next_shape_id);
1834rb_attr_delete(
VALUE obj,
ID id)
1836 return rb_ivar_delete(obj,
id,
Qnil);
1840imemo_fields_complex_from_obj_i(
ID key,
VALUE val, st_data_t arg)
1843 st_table *table = rb_imemo_fields_complex_tbl(fields);
1845 RUBY_ASSERT(!st_lookup(table, (st_data_t)key, NULL));
1846 st_add_direct(table, (st_data_t)key, (st_data_t)val);
1853imemo_fields_shref_i(
ID key,
VALUE val, st_data_t arg)
1860 rb_gc_writebarrier(fields_obj, val);
1868rb_imemo_fields_record_shrefs(
VALUE fields_obj)
1870 rb_field_foreach(fields_obj, imemo_fields_shref_i, (st_data_t)fields_obj,
false);
1874imemo_fields_complex_from_obj(
VALUE owner,
VALUE source, shape_id_t shape_id,
bool ivar_only,
int extra_capa)
1876 attr_index_t
len = source ? RSHAPE_LEN(RBASIC_SHAPE_ID(source)) : 0;
1877 int capa = (
len + extra_capa);
1882 rb_field_foreach(source, imemo_fields_complex_from_obj_i, (st_data_t)fields_obj, ivar_only);
1888imemo_fields_evacutate_to_complex(
VALUE owner,
VALUE source, shape_id_t shape_id,
int extra_capa)
1890 return imemo_fields_complex_from_obj(owner, source, shape_id,
false, extra_capa);
1894rb_obj_complex_fields_build(
VALUE obj)
1896 return imemo_fields_complex_from_obj(obj, obj, ROOT_COMPLEX_SHAPE_ID,
true, 0);
1900imemo_fields_copy_append(
VALUE owner,
VALUE source_fields_obj, shape_id_t current_shape_id, shape_id_t target_shape_id,
VALUE val)
1902 attr_index_t fields_count = RSHAPE_LEN(current_shape_id);
1906 VALUE *fields = rb_imemo_fields_ptr(fields_obj);
1908 if (source_fields_obj) {
1909 MEMCPY(fields, rb_imemo_fields_ptr(source_fields_obj),
VALUE, fields_count);
1910 for (attr_index_t i = 0; i < fields_count; i++) {
1921imemo_fields_set(
VALUE owner,
VALUE fields_obj, shape_id_t target_shape_id,
ID field_name,
VALUE val,
bool concurrent)
1923 const VALUE original_fields_obj = fields_obj;
1924 shape_id_t current_shape_id = fields_obj ? RBASIC_SHAPE_ID(fields_obj) : ROOT_SHAPE_ID;
1926 if (UNLIKELY(rb_shape_complex_p(target_shape_id))) {
1927 if (rb_shape_complex_p(current_shape_id)) {
1932 fields_obj = rb_imemo_fields_clone(fields_obj);
1936 fields_obj = imemo_fields_evacutate_to_complex(owner, original_fields_obj, target_shape_id, 1);
1937 current_shape_id = target_shape_id;
1940 st_table *table = rb_imemo_fields_complex_tbl(fields_obj);
1943 st_insert(table, (st_data_t)field_name, (st_data_t)val);
1945 RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
1948 attr_index_t index = RSHAPE_INDEX(target_shape_id);
1949 if (concurrent || index >= rb_shape_embedded_capacity(current_shape_id)) {
1950 return imemo_fields_copy_append(owner, original_fields_obj, current_shape_id, target_shape_id, val);
1953 VALUE *table = rb_imemo_fields_ptr(fields_obj);
1956 if (index >= RSHAPE_LEN(current_shape_id)) {
1957 RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
1965generic_field_set(
VALUE obj, shape_id_t target_shape_id,
ID field_name,
VALUE val)
1968 field_name = RSHAPE_EDGE_NAME(target_shape_id);
1972 const VALUE original_fields_obj = rb_obj_fields(obj, field_name);
1975 VALUE fields_obj = imemo_fields_set(obj, original_fields_obj, target_shape_id, field_name, val, concurrent);
1977 rb_obj_set_fields(obj, fields_obj, field_name, original_fields_obj);
1978 return rb_shape_complex_p(target_shape_id) ? ATTR_INDEX_NOT_SET : RSHAPE_INDEX(target_shape_id);
1982generic_shape_ivar(
VALUE obj,
ID id,
bool *new_ivar_out)
1984 bool new_ivar =
false;
1985 shape_id_t current_shape_id = RBASIC_SHAPE_ID(obj);
1986 shape_id_t target_shape_id = current_shape_id;
1988 if (!rb_shape_complex_p(current_shape_id)) {
1989 if (!rb_shape_find_ivar(current_shape_id,
id, &target_shape_id)) {
1991 target_shape_id = rb_obj_shape_transition_add_ivar(obj,
id);
1995 *new_ivar_out = new_ivar;
1996 return target_shape_id;
2003 shape_id_t target_shape_id = generic_shape_ivar(obj,
id, &dontcare);
2004 return generic_field_set(obj, target_shape_id,
id, val);
2008obj_field_set(
VALUE obj, shape_id_t target_shape_id,
ID field_name,
VALUE val)
2011 VALUE fields_obj = ROBJECT_FIELDS_OBJ(obj);
2012 shape_id_t current_shape_id = RBASIC_SHAPE_ID(obj);
2014 if (UNLIKELY(rb_shape_complex_p(target_shape_id))) {
2015 if (UNLIKELY(!rb_shape_complex_p(current_shape_id))) {
2016 current_shape_id = rb_obj_convert_too_complex(obj, fields_obj, current_shape_id);
2017 fields_obj = ROBJECT_FIELDS_OBJ(obj);
2024 field_name = RSHAPE_EDGE_NAME(target_shape_id);
2028 st_insert(rb_imemo_fields_complex_tbl(fields_obj), (st_data_t)field_name, (st_data_t)val);
2031 RBASIC_SET_SHAPE_ID(obj, target_shape_id);
2032 if (obj != fields_obj) {
2033 RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
2036 return ATTR_INDEX_NOT_SET;
2039 attr_index_t index = RSHAPE_INDEX(target_shape_id);
2041 if (index < RSHAPE_LEN(current_shape_id)) {
2043 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
2047 RUBY_ASSERT(index == RSHAPE_LEN(current_shape_id));
2049 if (UNLIKELY(index >= RSHAPE_CAPACITY(current_shape_id))) {
2050 fields_obj = imemo_fields_copy_append(obj, fields_obj, current_shape_id, target_shape_id, val);
2051 ROBJECT_SET_EXTENDED(obj, fields_obj);
2052 RBASIC_SET_FULL_SHAPE_ID(obj, rb_shape_transition_layout(target_shape_id, SHAPE_ID_LAYOUT_EXTENDED));
2055 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
2056 RBASIC_SET_SHAPE_ID(obj, target_shape_id);
2059 if (obj != fields_obj) {
2060 RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
2071 shape_id_t target_shape_id = generic_shape_ivar(obj,
id, &dontcare);
2072 return obj_field_set(obj, target_shape_id,
id, val);
2076rb_check_ivar_modifiable(
VALUE obj)
2078 if (UNLIKELY(!
RB_FL_ABLE(obj) || rb_shape_frozen_p(RBASIC_SHAPE_ID(obj)))) {
2079 rb_check_frozen(obj);
2083 rb_raise(rb_eRactorIsolationError,
2084 "can't modify instance variables of a shareable %"PRIsVALUE,
2087 else if (UNLIKELY(CHILLED_STRING_P(obj))) {
2088 CHILLED_STRING_MUTATED(obj);
2101 rb_check_ivar_modifiable(obj);
2102 obj_ivar_set(obj,
id, val);
2116 shape_id_t shape_id = rb_obj_shape_transition_frozen(x);
2121 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(x);
2126 fields_obj = rb_imemo_fields_new(x, ROOT_SHAPE_ID,
true);
2128 RCLASS_WRITABLE_SET_FIELDS_OBJ(x, fields_obj);
2132 RBASIC_SET_SHAPE_ID(x, shape_id);
2135 RBASIC_SET_SHAPE_ID(x, shape_id);
2145static attr_index_t class_ivar_set(
VALUE obj,
ID id,
VALUE val,
bool *new_ivar);
2150 RB_DEBUG_COUNTER_INC(ivar_set_base);
2154 return obj_ivar_set(obj,
id, val);
2158 class_ivar_set_ractor_check(obj,
id);
2160 return class_ivar_set(obj,
id, val, &dontcare);
2163 return generic_ivar_set(obj,
id, val);
2170 rb_check_ivar_modifiable(obj);
2171 ivar_set(obj,
id, val);
2178 return ivar_set(obj,
id, val);
2187 ivar_set(obj,
id, val);
2191rb_obj_field_set(
VALUE obj, shape_id_t target_shape_id,
ID field_name,
VALUE val)
2195 return obj_field_set(obj, target_shape_id, field_name, val);
2199 rb_bug(
"Unreachable");
2202 return generic_field_set(obj, target_shape_id, field_name, val);
2207ivar_defined0(
VALUE obj,
ID id)
2209 if (rb_obj_shape_complex_p(obj)) {
2211 VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
2212 st_table *table = rb_imemo_fields_complex_tbl(fields_obj);
2215 if (!table || !rb_st_lookup(table,
id, &idx)) {
2223 return RBOOL(rb_shape_get_iv_index(RBASIC_SHAPE_ID(obj),
id, &index));
2237 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
2239 defined = ivar_defined0(fields_obj,
id);
2244 defined = ivar_defined0(obj,
id);
2252 struct gen_fields_tbl *fields_tbl;
2254 rb_ivar_foreach_callback_func *func;
2256 shape_id_t shape_id;
2261iterate_over_shapes_callback(shape_id_t shape_id,
void *data)
2265 if (itr_data->ivar_only && !RSHAPE_TYPE_P(shape_id, SHAPE_IVAR)) {
2272 RUBY_ASSERT(!rb_obj_shape_complex_p(itr_data->obj));
2273 fields = ROBJECT_FIELDS(itr_data->obj);
2276 RUBY_ASSERT(IMEMO_TYPE_P(itr_data->obj, imemo_fields));
2277 RUBY_ASSERT(!rb_obj_shape_complex_p(itr_data->obj));
2279 fields = rb_imemo_fields_ptr(itr_data->obj);
2282 rb_bug(
"Unreachable");
2285 RUBY_ASSERT(itr_data->shape_id == RBASIC_SHAPE_ID(itr_data->obj));
2287 VALUE val = fields[RSHAPE_INDEX(shape_id)];
2288 int ret = itr_data->func(RSHAPE_EDGE_NAME(shape_id), val, itr_data->arg);
2290 RUBY_ASSERT(itr_data->shape_id == RBASIC_SHAPE_ID(itr_data->obj));
2299iterate_over_shapes(shape_id_t shape_id, rb_ivar_foreach_callback_func *callback,
struct iv_itr_data *itr_data)
2301 rb_shape_foreach_field(shape_id, iterate_over_shapes_callback, itr_data);
2305each_hash_iv(st_data_t
id, st_data_t val, st_data_t data)
2308 rb_ivar_foreach_callback_func *callback = itr_data->func;
2309 if ((
ID)
id == rb_shape_tree.id_object_id) {
2312 return callback((
ID)
id, (
VALUE)val, itr_data->arg);
2316obj_fields_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2322 .ivar_only = ivar_only,
2325 VALUE fields_obj = ROBJECT_FIELDS_OBJ(obj);
2326 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
2328 if (rb_shape_complex_p(shape_id)) {
2329 st_foreach_safe(rb_imemo_fields_complex_tbl(fields_obj), each_hash_iv, (st_data_t)&itr_data);
2332 itr_data.fields = rb_imemo_fields_ptr(fields_obj);
2333 itr_data.shape_id = shape_id;
2334 iterate_over_shapes(shape_id, func, &itr_data);
2339imemo_fields_each(
VALUE fields_obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2341 IMEMO_TYPE_P(fields_obj, imemo_fields);
2347 .ivar_only = ivar_only,
2350 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
2351 if (rb_shape_complex_p(shape_id)) {
2352 rb_st_foreach(rb_imemo_fields_complex_tbl(fields_obj), each_hash_iv, (st_data_t)&itr_data);
2355 itr_data.fields = rb_imemo_fields_ptr(fields_obj);
2356 itr_data.shape_id = shape_id;
2357 iterate_over_shapes(shape_id, func, &itr_data);
2364 VALUE new_fields_obj;
2366 rb_check_frozen(dest);
2368 if (!rb_obj_gen_fields_p(obj)) {
2372 shape_id_t src_shape_id = rb_obj_shape_id(obj);
2374 VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
2382 shape_id_t initial_shape_id = rb_obj_shape_id(dest);
2383 shape_id_t dest_shape_id = rb_shape_rebuild(initial_shape_id, src_shape_id);
2385 if (UNLIKELY(rb_shape_complex_p(dest_shape_id))) {
2386 rb_obj_replace_fields(dest, rb_obj_complex_fields_build(obj));
2390 if (!RSHAPE_LEN(dest_shape_id)) {
2391 RBASIC_SET_SHAPE_ID(dest, dest_shape_id);
2396 VALUE *src_buf = rb_imemo_fields_ptr(fields_obj);
2397 VALUE *dest_buf = rb_imemo_fields_ptr(new_fields_obj);
2398 rb_shape_copy_fields(new_fields_obj, dest_buf, dest_shape_id, src_buf, src_shape_id);
2400 rb_obj_replace_fields(dest, new_fields_obj);
2408rb_generic_fields_shared_table_foreach(
void (*cb)(
struct st_table *tbl,
void *arg),
void *arg)
2411 if (generic_fields_tbl_ != NULL) {
2412 cb(generic_fields_tbl_, arg);
2421rb_generic_fields_tables_foreach(
void (*cb)(
struct st_table *tbl,
void *arg),
void *arg)
2423 if (generic_fields_tbl_ != NULL) {
2424 cb(generic_fields_tbl_, arg);
2429rb_field_foreach(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2434 if (IMEMO_TYPE_P(obj, imemo_fields)) {
2435 imemo_fields_each(obj, func, arg, ivar_only);
2439 obj_fields_each(obj, func, arg, ivar_only);
2446 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
2448 imemo_fields_each(fields_obj, func, arg, ivar_only);
2454 VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
2456 imemo_fields_each(fields_obj, func, arg, ivar_only);
2469collect_ivar_i(
ID id,
VALUE val, st_data_t arg)
2481 rb_field_foreach(obj, func, arg,
true);
2485rb_ivar_foreach_buffered(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
2488 if (count == 0)
return;
2494 rb_field_foreach(obj, collect_ivar_i, (st_data_t)&pos,
true);
2497 for (st_index_t i = 0; i < count; i++) {
2498 if (func(buf[i].name, buf[i].val, arg) == ST_STOP)
break;
2509 st_index_t iv_count = 0;
2510 VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
2513 if (rb_obj_shape_complex_p(fields_obj)) {
2514 iv_count = rb_st_table_size(rb_imemo_fields_complex_tbl(fields_obj));
2517 iv_count = RBASIC_FIELDS_COUNT(obj);
2521 if (rb_obj_shape_has_id(obj)) {
2529ivar_i(
ID key,
VALUE v, st_data_t a)
2564#define rb_is_constant_id rb_is_const_id
2565#define rb_is_constant_name rb_is_const_name
2566#define id_for_var(obj, name, part, type) \
2567 id_for_var_message(obj, name, type, "'%1$s' is not allowed as "#part" "#type" variable name")
2568#define id_for_var_message(obj, name, type, message) \
2569 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
2572 int (*valid_id_p)(
ID),
int (*valid_name_p)(
VALUE),
2573 const char *message,
size_t message_len)
2576 VALUE name = *pname;
2578 if (
id ? !valid_id_p(
id) : !valid_name_p(name)) {
2579 rb_name_err_raise_str(rb_fstring_new(message, message_len),
2611 const ID id = id_for_var(obj, name, an, instance);
2615 rb_check_frozen(obj);
2620 if (!UNDEF_P(val))
return val;
2623 rb_name_err_raise(
"instance variable %1$s not defined",
2628NORETURN(
static void uninitialized_constant(
VALUE,
VALUE));
2630uninitialized_constant(
VALUE klass,
VALUE name)
2633 rb_name_err_raise(
"uninitialized constant %2$s::%1$s",
2636 rb_name_err_raise(
"uninitialized constant %1$s",
2644 rb_vm_inc_const_missing_count();
2693 VALUE ref = ec->private_const_reference;
2694 rb_vm_pop_cfunc_frame();
2696 ec->private_const_reference = 0;
2697 rb_name_err_raise(
"private constant %2$s::%1$s referenced", ref, name);
2699 uninitialized_constant(klass, name);
2707 struct ccan_list_node cnode;
2710 VALUE autoload_data_value;
2720 VALUE autoload_call_file;
2729 rb_const_flag_t flag;
2745 rb_serial_t fork_gen;
2748 struct ccan_list_head constants;
2752autoload_data_mark_and_move(
void *ptr)
2756 rb_gc_mark_and_move(&p->feature);
2757 rb_gc_mark_and_move(&p->mutex);
2761autoload_data_free(
void *ptr)
2766 ccan_list_for_each_safe(&p->constants,
autoload_const, next, cnode) {
2774autoload_data_memsize(
const void *ptr)
2781 {autoload_data_mark_and_move, autoload_data_free, autoload_data_memsize, autoload_data_mark_and_move},
2786autoload_const_mark_and_move(
void *ptr)
2790 rb_gc_mark_and_move(&ac->module);
2791 rb_gc_mark_and_move(&ac->autoload_call_file);
2792 rb_gc_mark_and_move(&ac->autoload_data_value);
2793 rb_gc_mark_and_move(&ac->value);
2794 rb_gc_mark_and_move(&ac->file);
2795 rb_gc_mark_and_move(&ac->box_value);
2799autoload_const_memsize(
const void *ptr)
2805autoload_const_free(
void *ptr)
2815 {autoload_const_mark_and_move, autoload_const_free, autoload_const_memsize, autoload_const_mark_and_move,},
2820get_autoload_data(
VALUE autoload_const_value,
struct autoload_const **autoload_const_pointer)
2833 if (autoload_const_pointer) *autoload_const_pointer =
autoload_const;
2840autoload_entry(
VALUE mod,
ID id)
2843 if (!ce || !UNDEF_P(ce->value))
return 0;
2844 VM_ASSERT(rb_typeddata_is_kind_of(ce->u.autoload_const, &autoload_const_type));
2845 return ce->u.autoload_const;
2850static void const_added(
VALUE klass,
ID const_name);
2860autoload_feature_lookup_or_create(
VALUE feature,
struct autoload_data **autoload_data_pointer)
2862 RUBY_ASSERT_MUTEX_OWNED(autoload_mutex);
2863 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2865 VALUE autoload_data_value = rb_hash_aref(autoload_features, feature);
2868 if (
NIL_P(autoload_data_value)) {
2874 if (autoload_data_pointer) *autoload_data_pointer =
autoload_data;
2876 rb_hash_aset(autoload_features, feature, autoload_data_value);
2878 else if (autoload_data_pointer) {
2879 *autoload_data_pointer =
rb_check_typeddata(autoload_data_value, &autoload_data_type);
2882 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2883 return autoload_data_value;
2887autoload_synchronized(
VALUE _arguments)
2891 rb_const_entry_t *constant_entry = rb_const_lookup(arguments->module, arguments->name);
2892 if (constant_entry && !UNDEF_P(constant_entry->value)) {
2897 const_set(arguments->module, arguments->name,
Qundef);
2898 constant_entry = rb_const_lookup(arguments->module, arguments->name);
2901 VALUE feature = rb_fstring(arguments->feature);
2904 VALUE autoload_data_value = autoload_feature_lookup_or_create(feature, &
autoload_data);
2917 RB_OBJ_WRITE(arguments->module, &constant_entry->u.autoload_const, autoload_const_value);
2926 const rb_box_t *box = rb_current_box();
2927 VALUE current_box_value = rb_get_box_object((
rb_box_t *)box);
2930 rb_raise(
rb_eNameError,
"autoload must be constant name: %"PRIsVALUE
"", QUOTE_ID(name));
2933 rb_class_owner_check(module);
2936 if (!RSTRING_LEN(feature)) {
2937 rb_raise(rb_eArgError,
"empty feature name");
2944 .box_value = current_box_value,
2949 if (result ==
Qtrue) {
2950 const_added(module, name);
2955autoload_delete(
VALUE autoload_const_value)
2957 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2959 VM_ASSERT(rb_typeddata_is_kind_of(autoload_const_value, &autoload_const_type));
2977 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2987check_autoload_required(
VALUE mod,
ID id,
const char **loadingpath)
2989 VALUE autoload_const_value = autoload_entry(mod,
id);
2991 const char *loading;
2993 if (!autoload_const_value || !(
autoload_data = get_autoload_data(autoload_const_value, 0))) {
3006 return autoload_const_value;
3009 loading = RSTRING_PTR(feature);
3012 return autoload_const_value;
3015 if (loadingpath && loading) {
3016 *loadingpath = loading;
3017 return autoload_const_value;
3026rb_autoloading_value(
VALUE mod,
ID id,
VALUE* value, rb_const_flag_t *flag)
3029 if (!ac)
return FALSE;
3045 return ele->mutex !=
Qnil && rb_mutex_owned_p(ele->mutex);
3052autoloading_const_entry(
VALUE mod,
ID id)
3054 VALUE load = autoload_entry(mod,
id);
3059 if (!load || !(ele = get_autoload_data(load, &ac))) {
3065 if (autoload_by_current(ele)) {
3066 if (!UNDEF_P(ac->value)) {
3075autoload_defined_p(
VALUE mod,
ID id)
3080 if (!ce || !UNDEF_P(ce->value)) {
3086 return !rb_autoloading_value(mod,
id, NULL, NULL);
3105 if (!warning->id)
return;
3107 VALUE name = QUOTE_ID(warning->id);
3110 if (!
NIL_P(warning->file) && warning->line) {
3111 previous = rb_sprintf(
"\n%"PRIsVALUE
":%d: warning: previous definition of %"PRIsVALUE
" was here",
3112 warning->file, warning->line, name);
3116 rb_warn(
"already initialized constant %"PRIsVALUE
"%"PRIsVALUE
"", name, previous);
3119 rb_warn(
"already initialized constant %"PRIsVALUE
"::%"PRIsVALUE
"%"PRIsVALUE
"",
3141 check_before_mod_set(ac->module, ac->name, ac->value,
"constant");
3145 const_tbl_update(ac,
true, &warning);
3147 const_warning_emit(&warning);
3153autoload_load_needed(
VALUE _arguments)
3157 const char *loading = 0, *src;
3159 if (!autoload_defined_p(arguments->module, arguments->name)) {
3163 VALUE autoload_const_value = check_autoload_required(arguments->module, arguments->name, &loading);
3164 if (!autoload_const_value) {
3169 if (src && loading && strcmp(src, loading) == 0) {
3190 return autoload_const_value;
3194autoload_apply_constants(
VALUE _arguments)
3196 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3208 ccan_list_for_each_safe(&arguments->autoload_data->constants,
autoload_const, next, cnode) {
3214 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3221autoload_require_and_apply(
VALUE receiver,
VALUE _arguments)
3225 VALUE result =
rb_funcall(receiver, rb_intern(
"require"), 1, arguments->autoload_data->feature);
3226 if (
RTEST(result)) {
3233autoload_feature_require_in_box(
VALUE receiver,
VALUE _arguments)
3235 rb_vm_frame_flag_set_box_require(GET_EC());
3237 return autoload_require_and_apply(receiver, _arguments);
3241autoload_feature_require(
VALUE _arguments)
3257 rb_gccct_clear_table();
3259 VALUE feature = arguments->autoload_data->feature;
3261 if (rb_box_available() && BOX_OBJ_P(autoload_box_value)) {
3262 box = rb_get_box_t(autoload_box_value);
3265 if (box && box->top_self) {
3271 return rb_vm_call_cfunc_in_box(box->top_self, autoload_feature_require_in_box,
3272 box->top_self, _arguments, feature, box);
3274 return autoload_require_and_apply(rb_vm_top_self(), _arguments);
3283 if (rb_box_available() && BOX_OBJ_P(ac->box_value)) {
3284 const rb_box_t *box = rb_get_box_t(ac->box_value);
3285 if (box->top_self)
return box;
3287 return rb_current_box();
3294 return const_lookup(RCLASSEXT_CONST_TBL(RCLASS_EXT_READABLE_IN_BOX(mod, box)),
id);
3298autoload_try_load(
VALUE _arguments)
3303 VALUE result = autoload_feature_require(_arguments);
3306 rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name);
3311 if (ce && UNDEF_P(ce->value)) {
3312 rb_const_entry_t *loaded = const_lookup_in_box(arguments->module, arguments->name,
3313 autoload_box(arguments->autoload_const));
3314 if (loaded && !UNDEF_P(loaded->value)) {
3316 ce->flag = loaded->flag;
3317 RB_OBJ_WRITE(arguments->module, &ce->value, loaded->value);
3318 RB_OBJ_WRITE(arguments->module, &ce->u.file, loaded->u.file);
3319 ce->line = loaded->line;
3326 if (!ce || UNDEF_P(ce->value)) {
3333 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
" but it didn't",
3334 arguments->autoload_data->feature,
3340 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
"::%"PRIsVALUE
" but it didn't",
3341 arguments->autoload_data->feature,
3349 ce->flag |= arguments->flag;
3361 if (!ce || !UNDEF_P(ce->value)) {
3366 if (UNLIKELY(!rb_ractor_main_p())) {
3367 return rb_ractor_autoload_load(module, name);
3377 if (autoload_const_value ==
Qfalse)
return autoload_const_value;
3379 arguments.flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
3396 return rb_autoload_at_p(mod,
id, TRUE);
3400rb_autoload_at_p(
VALUE mod,
ID id,
int recur)
3405 while (!autoload_defined_p(mod,
id)) {
3406 if (!recur)
return Qnil;
3408 if (!mod)
return Qnil;
3410 load = check_autoload_required(mod,
id, 0);
3411 if (!load)
return Qnil;
3412 return (ele = get_autoload_data(load, 0)) ? ele->feature :
Qnil;
3418 if (RB_CONST_DEPRECATED_P(ce) &&
3431rb_const_unshareable_error(
VALUE klass,
ID id)
3433 rb_raise(rb_eRactorIsolationError,
"can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" of a class/module created by another Ractor.",
rb_class_path(klass), rb_id2str(
id));
3437rb_const_get_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3440 VALUE c = rb_const_search(klass,
id, exclude, recurse, visibility, &found_in);
3444 return rb_const_missing(klass,
ID2SYM(
id));
3448rb_const_search_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility,
VALUE *found_in)
3450 VALUE value, current;
3451 bool first_iteration =
true;
3453 for (current = klass;
3455 current =
RCLASS_SUPER(current), first_iteration =
false) {
3460 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
3473 while (rb_const_lookup_copy(tmp,
id, ce)) {
3474 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3475 GET_EC()->private_const_reference = tmp;
3480 if (!UNDEF_P(value) && UNLIKELY(!rb_class_owned_p(tmp)) && !rb_class_field_shareable_p(tmp, value)) {
3481 rb_const_warn_if_deprecated(ce, tmp,
id);
3482 rb_const_unshareable_error(tmp,
id);
3484 rb_const_warn_if_deprecated(ce, tmp,
id);
3485 if (UNDEF_P(value)) {
3487 if (am == tmp)
break;
3489 ac = autoloading_const_entry(tmp,
id);
3491 if (found_in) { *found_in = tmp; }
3492 if (UNLIKELY(!rb_class_owned_p(tmp)) && !rb_class_field_shareable_p(tmp, ac->value)) {
3493 rb_const_unshareable_error(tmp,
id);
3503 if (found_in) { *found_in = tmp; }
3506 if (!recurse)
break;
3510 GET_EC()->private_const_reference = 0;
3515rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility,
VALUE *found_in)
3520 value = rb_const_search_from(klass,
id, exclude, recurse, visibility, found_in);
3521 if (!UNDEF_P(value))
return value;
3522 if (exclude)
return value;
3525 return rb_const_search_from(
rb_cObject,
id, FALSE, recurse, visibility, found_in);
3531 return rb_const_get_0(klass,
id, TRUE, TRUE, FALSE);
3537 return rb_const_get_0(klass,
id, FALSE, TRUE, FALSE);
3543 return rb_const_get_0(klass,
id, TRUE, FALSE, FALSE);
3547rb_public_const_get_from(
VALUE klass,
ID id)
3549 return rb_const_get_0(klass,
id, TRUE, TRUE, TRUE);
3553rb_public_const_get_at(
VALUE klass,
ID id)
3555 return rb_const_get_0(klass,
id, TRUE, FALSE, TRUE);
3558NORETURN(
static void undefined_constant(
VALUE mod,
VALUE name));
3562 rb_name_err_raise(
"constant %2$s::%1$s not defined",
3567rb_const_location_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3569 while (
RTEST(klass)) {
3572 while (rb_const_lookup_copy(klass,
id, ce)) {
3573 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3580 VALUE file = ce->u.file;
3581 VALUE autoload_const_value = autoload_entry(klass,
id);
3582 if (autoload_const_value) {
3595 if (!recurse)
break;
3604rb_const_location(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3609 loc = rb_const_location_from(klass,
id, exclude, recurse, visibility);
3610 if (!
NIL_P(loc))
return loc;
3611 if (exclude)
return loc;
3614 return rb_const_location_from(
rb_cObject,
id, FALSE, recurse, visibility);
3618rb_const_source_location(
VALUE klass,
ID id)
3620 return rb_const_location(klass,
id, FALSE, TRUE, FALSE);
3624rb_const_source_location_at(
VALUE klass,
ID id)
3626 return rb_const_location(klass,
id, TRUE, FALSE, FALSE);
3642 const ID id = id_for_var(mod, name, a, constant);
3645 undefined_constant(mod, name);
3658 rb_check_frozen(mod);
3659 rb_class_owner_check(mod);
3661 ce = rb_const_lookup(mod,
id);
3665 rb_name_err_raise(
"cannot remove %2$s::%1$s", mod,
ID2SYM(
id));
3668 undefined_constant(mod,
ID2SYM(
id));
3671 VALUE writable_ce = 0;
3674 found = rb_id_table_lookup(RCLASS_WRITABLE_CONST_TBL(mod),
id, &writable_ce);
3675 if (found) rb_id_table_delete(RCLASS_WRITABLE_CONST_TBL(mod),
id);
3681 rb_const_warn_if_deprecated(ce, mod,
id);
3687 autoload_delete(ce->u.autoload_const);
3691 if (ce != const_lookup(RCLASS_PRIME_CONST_TBL(mod),
id)) {
3700cv_i_update(st_data_t *k, st_data_t *v, st_data_t a,
int existing)
3702 if (existing)
return ST_STOP;
3707static enum rb_id_table_iterator_result
3714 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
3716 return ID_TABLE_CONTINUE;
3719static enum rb_id_table_iterator_result
3720rb_local_constants_i(
ID const_name,
VALUE const_value,
void *ary)
3725 return ID_TABLE_CONTINUE;
3729rb_local_constants(
VALUE mod)
3738 rb_id_table_foreach(tbl, rb_local_constants_i, (
void *)ary);
3749 tbl = st_init_numtable();
3751 if (RCLASS_CONST_TBL(mod)) {
3753 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
3773list_i(st_data_t key, st_data_t value,
VALUE ary)
3816 bool inherit =
true;
3824 return rb_local_constants(mod);
3829rb_const_defined_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3838 if (rb_const_lookup_copy(tmp,
id, ce)) {
3839 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3842 if (UNDEF_P(ce->value) && !check_autoload_required(tmp,
id, 0) &&
3843 !rb_autoloading_value(tmp,
id, NULL, NULL))
3852 if (!recurse)
break;
3866 return rb_const_defined_0(klass,
id, TRUE, TRUE, FALSE);
3872 return rb_const_defined_0(klass,
id, FALSE, TRUE, FALSE);
3878 return rb_const_defined_0(klass,
id, TRUE, FALSE, FALSE);
3882rb_public_const_defined_from(
VALUE klass,
ID id)
3884 return rb_const_defined_0(klass,
id, TRUE, TRUE, TRUE);
3888check_before_mod_set(
VALUE klass,
ID id,
VALUE val,
const char *dest)
3890 rb_check_frozen(klass);
3893static void set_namespace_path(
VALUE named_namespace,
VALUE name);
3895static enum rb_id_table_iterator_result
3896set_namespace_path_i(
ID id,
VALUE v,
void *payload)
3899 VALUE value = ce->value;
3902 return ID_TABLE_CONTINUE;
3905 bool has_permanent_classpath;
3906 classname(value, &has_permanent_classpath);
3907 if (has_permanent_classpath) {
3908 return ID_TABLE_CONTINUE;
3910 set_namespace_path(value, build_const_path(parental_path,
id));
3912 if (!RCLASS_PERMANENT_CLASSPATH_P(value)) {
3913 RCLASS_WRITE_CLASSPATH(value, 0,
false);
3916 return ID_TABLE_CONTINUE;
3925set_namespace_path(
VALUE named_namespace,
VALUE namespace_path)
3927 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3931 RCLASS_WRITE_CLASSPATH(named_namespace, namespace_path,
true);
3934 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3940const_added(
VALUE klass,
ID const_name)
3942 if (GET_VM()->running) {
3944 rb_funcallv_uncached(klass, idConst_added, 1, &arg);
3954 rb_raise(
rb_eTypeError,
"no class/module to define constant %"PRIsVALUE
"",
3958 if (UNLIKELY(!rb_class_owned_p(klass))) {
3959 rb_raise(rb_eRactorIsolationError,
"can not set constants of classes/modules created by another Ractor");
3962 check_before_mod_set(klass,
id, val,
"constant");
3966 struct rb_id_table *tbl = RCLASS_WRITABLE_CONST_TBL(klass);
3968 tbl = rb_id_table_create(0);
3969 RCLASS_WRITE_CONST_TBL(klass, tbl,
false);
3972 rb_id_table_insert(tbl,
id, (
VALUE)ce);
3973 setup_const_entry(ce, klass, val, CONST_PUBLIC);
3977 .module = klass, .name = id,
3978 .value = val, .flag = CONST_PUBLIC,
3981 ac.file = rb_source_location(&ac.line);
3982 const_tbl_update(&ac,
false, &warning);
3985 const_warning_emit(&warning);
3992 bool val_path_permanent;
3993 VALUE val_path = classname(val, &val_path_permanent);
3994 if (
NIL_P(val_path) || !val_path_permanent) {
3996 set_namespace_path(val, rb_id2str(
id));
3999 bool parental_path_permanent;
4000 VALUE parental_path = classname(klass, &parental_path_permanent);
4001 if (
NIL_P(parental_path)) {
4003 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
4005 if (parental_path_permanent && !val_path_permanent) {
4006 set_namespace_path(val, build_const_path(parental_path,
id));
4008 else if (!parental_path_permanent &&
NIL_P(val_path)) {
4009 VALUE path = build_const_path(parental_path,
id);
4010 RCLASS_SET_CLASSPATH(val, path,
false);
4020 const_set(klass,
id, val);
4021 const_added(klass,
id);
4025autoload_const_value_for_named_constant(
VALUE module,
ID name,
struct autoload_const **autoload_const_pointer)
4027 VALUE autoload_const_value = autoload_entry(module, name);
4028 if (!autoload_const_value)
return Qfalse;
4035 return autoload_const_value;
4045 ASSERT_vm_locking();
4047 VALUE klass = ac->module;
4048 VALUE val = ac->value;
4050 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4051 rb_const_flag_t visibility = ac->flag;
4054 if (rb_id_table_lookup(tbl,
id, &value)) {
4056 if (UNDEF_P(ce->value)) {
4057 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
4058 VALUE file = ac->file;
4059 int line = ac->line;
4060 VALUE autoload_const_value = autoload_const_value_for_named_constant(klass,
id, &ac);
4062 if (!autoload_force && autoload_const_value) {
4066 RB_OBJ_WRITE(autoload_const_value, &ac->file, rb_source_location(&ac->line));
4070 autoload_delete(ce->u.autoload_const);
4071 ce->flag = visibility;
4076 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
4080 visibility = ce->flag;
4083 warning->module = klass;
4084 warning->file = ce->u.file;
4085 warning->line = ce->line;
4088 setup_const_entry(ce, klass, val, visibility);
4091 tbl = RCLASS_WRITABLE_CONST_TBL(klass);
4095 rb_id_table_insert(tbl,
id, (
VALUE)ce);
4096 setup_const_entry(ce, klass, val, visibility);
4102 rb_const_flag_t visibility)
4104 ce->flag = visibility;
4106 RB_OBJ_WRITE(klass, &ce->u.file, rb_source_location(&ce->line));
4112 ID id = rb_intern(name);
4115 rb_warn(
"rb_define_const: invalid name '%s' for constant", name);
4118 rb_vm_register_global_object(val);
4130set_const_visibility(
VALUE mod,
int argc,
const VALUE *argv,
4131 rb_const_flag_t flag, rb_const_flag_t mask)
4139 rb_warning(
"%"PRIsVALUE
" with no argument is just ignored",
4140 QUOTE_ID(rb_frame_callee()));
4144 for (i = 0; i < argc; i++) {
4146 VALUE val = argv[i];
4149 undefined_constant(mod, val);
4151 if ((ce = rb_const_lookup(mod,
id))) {
4154 if (UNDEF_P(ce->value)) {
4155 if (autoload_const_value_for_named_constant(mod,
id, &ac)) {
4163 undefined_constant(mod,
ID2SYM(
id));
4173 long len = strlen(name);
4177 undefined_constant(mod, rb_fstring_new(name,
len));
4179 if (!(ce = rb_const_lookup(mod,
id))) {
4180 undefined_constant(mod,
ID2SYM(
id));
4182 ce->flag |= CONST_DEPRECATED;
4193rb_mod_private_constant(
int argc,
const VALUE *argv,
VALUE obj)
4195 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
4207rb_mod_public_constant(
int argc,
const VALUE *argv,
VALUE obj)
4209 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
4233rb_mod_deprecate_constant(
int argc,
const VALUE *argv,
VALUE obj)
4235 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
4240original_module(
VALUE c)
4248cvar_lookup_at(
VALUE klass,
ID id, st_data_t *v)
4251 if (RICLASS_IS_ORIGIN_P(klass)) {
4256 klass =
RBASIC(klass)->klass;
4261 if (UNDEF_P(n))
return 0;
4268cvar_front_klass(
VALUE klass)
4270 if (RCLASS_SINGLETON_P(klass)) {
4271 VALUE obj = RCLASS_ATTACHED_OBJECT(klass);
4272 if (rb_namespace_p(obj)) {
4282 if (front && target != front && original_module(front) != original_module(target)) {
4284 "class variable % "PRIsVALUE
" of %"PRIsVALUE
" is overtaken by %"PRIsVALUE
"",
4294 if (front && target != front) {
4297 rb_ivar_delete(front,
id,
Qundef);
4302#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
4303 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
4304 if (cvar_lookup_at(klass, id, (v))) { \
4309#define CVAR_LOOKUP(v,r) do {\
4310 if (cvar_lookup_at(klass, id, (v))) {r;}\
4311 CVAR_FOREACH_ANCESTORS(klass, v, r);\
4331 VALUE tmp, front = 0, target = 0;
4334 CVAR_LOOKUP(0, {
if (!front) front = klass; target = klass;});
4336 cvar_overtaken_check(front, target,
id);
4337 cvar_overtaken(front, target,
id);
4344 target =
RBASIC(target)->klass;
4346 cvar_set_ractor_check(target,
id);
4347 check_before_mod_set(target,
id, val,
"class variable");
4349 bool new_cvar = rb_class_ivar_set(target,
id, val);
4351 VALUE cvc_tbl = RCLASS_WRITABLE_CVC_TBL(target);
4356 if (!cvc_tbl || !rb_marked_id_table_lookup(cvc_tbl,
id, &ent_data)) {
4360 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
4362 VALUE new_cvc_tbl = cvc_tbl;
4364 new_cvc_tbl = rb_marked_id_table_new(2);
4366 else if (rb_multi_ractor_p()) {
4367 new_cvc_tbl = rb_marked_id_table_dup(cvc_tbl);
4370 rb_marked_id_table_insert(new_cvc_tbl,
id, (
VALUE)ent);
4371 if (new_cvc_tbl != cvc_tbl) {
4372 RCLASS_WRITE_CVC_TBL(target, new_cvc_tbl);
4374 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
4377 ent = (
void *)ent_data;
4378 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
4385 ruby_vm_global_cvar_state++;
4395 value = find_cvar(klass, front, &target,
id);
4397 rb_name_err_raise(
"uninitialized class variable %1$s in %2$s",
4400 cvar_overtaken_check(*front, target,
id);
4403 cvar_overtaken(*front, target,
id);
4417 if (!klass)
return Qfalse;
4418 CVAR_LOOKUP(0,
return Qtrue);
4423cv_intern(
VALUE klass,
const char *name)
4425 ID id = rb_intern(name);
4427 rb_name_err_raise(
"wrong class variable name %1$s",
4436 ID id = cv_intern(klass, name);
4443 ID id = cv_intern(klass, name);
4454cv_i(
ID key,
VALUE v, st_data_t a)
4459 st_update(tbl, (st_data_t)key, cv_i_update, 0);
4465mod_cvar_at(
VALUE mod,
void *data)
4469 tbl = st_init_numtable();
4471 mod = original_module(mod);
4478mod_cvar_of(
VALUE mod,
void *data)
4481 if (RCLASS_SINGLETON_P(mod)) {
4482 if (rb_namespace_p(RCLASS_ATTACHED_OBJECT(mod))) {
4483 data = mod_cvar_at(tmp, data);
4484 tmp = cvar_front_klass(tmp);
4488 data = mod_cvar_at(tmp, data);
4496cv_list_i(st_data_t key, st_data_t value,
VALUE ary)
4504cvar_list(
void *data)
4540 bool inherit =
true;
4545 tbl = mod_cvar_of(mod, 0);
4548 tbl = mod_cvar_at(mod, 0);
4550 return cvar_list(tbl);
4575 const ID id = id_for_var_message(mod, name,
class,
"wrong class variable name %1$s");
4581 rb_check_frozen(mod);
4582 cvar_set_ractor_check(mod,
id);
4583 val = rb_ivar_delete(mod,
id,
Qundef);
4584 if (!UNDEF_P(val)) {
4588 rb_name_err_raise(
"cannot remove %1$s for %2$s", mod,
ID2SYM(
id));
4591 rb_name_err_raise(
"class variable %1$s not defined for %2$s",
4610 ID id = rb_intern(name);
4616class_fields_ivar_set(
VALUE klass,
VALUE fields_obj,
ID id,
VALUE val,
bool concurrent,
VALUE *new_fields_obj,
bool *new_ivar_out)
4618 const VALUE original_fields_obj = fields_obj;
4619 fields_obj = original_fields_obj ? original_fields_obj : rb_imemo_fields_new(klass, ROOT_SHAPE_ID,
true);
4621 shape_id_t current_shape_id = RBASIC_SHAPE_ID(fields_obj);
4622 shape_id_t next_shape_id = current_shape_id;
4623 if (UNLIKELY(rb_shape_complex_p(current_shape_id))) {
4628 next_shape_id = generic_shape_ivar(fields_obj,
id, &new_ivar);
4630 if (UNLIKELY(rb_shape_complex_p(next_shape_id))) {
4631 fields_obj = imemo_fields_evacutate_to_complex(klass, fields_obj, next_shape_id, 1);
4635 attr_index_t index = RSHAPE_INDEX(next_shape_id);
4636 if (new_ivar && index >= RSHAPE_CAPACITY(current_shape_id)) {
4639 fields_obj = imemo_fields_copy_append(klass, fields_obj, current_shape_id, next_shape_id, val);
4642 VALUE *fields = rb_imemo_fields_ptr(fields_obj);
4644 if (concurrent && original_fields_obj == fields_obj) {
4650 RB_OBJ_ATOMIC_WRITE(fields_obj, &fields[index], val);
4657 RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
4658 RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
4662 *new_fields_obj = fields_obj;
4663 *new_ivar_out = new_ivar;
4668 if (concurrent && fields_obj == original_fields_obj) {
4672 fields_obj = rb_imemo_fields_clone(fields_obj);
4675 st_table *table = rb_imemo_fields_complex_tbl(fields_obj);
4676 new_ivar = !st_insert(table, (st_data_t)
id, (st_data_t)val);
4679 if (fields_obj != original_fields_obj) {
4680 RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
4681 RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
4685 *new_fields_obj = fields_obj;
4686 *new_ivar_out = new_ivar;
4687 return ATTR_INDEX_NOT_SET;
4691class_ivar_set(
VALUE obj,
ID id,
VALUE val,
bool *new_ivar)
4693 rb_class_ensure_writable(obj);
4695 const VALUE original_fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
4696 VALUE new_fields_obj = 0;
4698 attr_index_t index = class_fields_ivar_set(obj, original_fields_obj,
id, val, rb_multi_ractor_p(), &new_fields_obj, new_ivar);
4700 if (new_fields_obj != original_fields_obj) {
4701 RCLASS_WRITABLE_SET_FIELDS_OBJ(obj, new_fields_obj);
4707 RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(new_fields_obj));
4715 rb_check_frozen(obj);
4718 class_ivar_set(obj,
id, val, &new_ivar);
4727 RUBY_ASSERT(RSHAPE_TYPE_P(RBASIC_SHAPE_ID(dst), SHAPE_ROOT));
4729 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(src);
4731 VALUE dst_fields_obj = rb_imemo_fields_clone(fields_obj);
4734 shape_id_t shape_id = RBASIC_SHAPE_ID(dst_fields_obj) & ~SHAPE_ID_FL_FROZEN;
4735 RBASIC_SET_SHAPE_ID(dst_fields_obj, shape_id);
4736 RCLASS_WRITABLE_SET_FIELDS_OBJ(dst, dst_fields_obj);
4737 RBASIC_SET_SHAPE_ID(dst, shape_id);
4748 r = rb_id_table_lookup(tbl,
id, &val);
4757rb_const_lookup(
VALUE klass,
ID id)
4759 return const_lookup(RCLASS_CONST_TBL(klass),
id);
4769 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4771 if (tbl && rb_id_table_lookup(tbl,
id, &entry)) {
#define RUBY_EXTERN
Declaration of externally visible global variables.
static VALUE RB_OBJ_FROZEN_RAW(VALUE obj)
This is an implementation detail of RB_OBJ_FROZEN().
static bool RB_FL_ABLE(VALUE obj)
Checks if the object is flaggable.
static void RB_FL_SET_RAW(VALUE obj, VALUE flags)
This is an implementation detail of RB_FL_SET().
void rb_obj_freeze_inline(VALUE obj)
Prevents further modifications to the given object.
static void RB_FL_UNSET_RAW(VALUE obj, VALUE flags)
This is an implementation detail of RB_FL_UNSET().
@ RUBY_FL_FREEZE
This flag has something to do with data immutability.
void rb_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
void rb_freeze_singleton_class(VALUE attached_object)
This is an implementation detail of RB_OBJ_FREEZE().
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define TYPE(_)
Old name of rb_type.
#define ALLOC
Old name of RB_ALLOC.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define ID2SYM
Old name of RB_ID2SYM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define T_STRUCT
Old name of RUBY_T_STRUCT.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define T_DATA
Old name of RUBY_T_DATA.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define FL_USER2
Old name of RUBY_FL_USER2.
#define Qtrue
Old name of RUBY_Qtrue.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
void rb_name_error(ID id, const char *fmt,...)
Raises an instance of rb_eNameError.
VALUE rb_eTypeError
TypeError exception.
void rb_name_error_str(VALUE str, const char *fmt,...)
Identical to rb_name_error(), except it takes a VALUE instead of ID.
VALUE rb_eNameError
NameError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
void rb_warning(const char *fmt,...)
Issues a warning.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_cObject
Object class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_cModule
Module class.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
ID rb_check_id_cstr(const char *ptr, rb_len_t len, rb_encoding *enc)
Identical to rb_check_id(), except it takes a pointer to a memory region instead of Ruby's string.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_ary_new_capa(rb_len_t capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_hidden_new(rb_len_t capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
#define st_foreach_safe
Just another name of rb_st_foreach_safe.
int rb_feature_provided(const char *feature, const char **loading)
Identical to rb_provided(), except it additionally returns the "canonical" name of the loaded feature...
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
int rb_is_instance_id(ID id)
Classifies the given ID, then sees if it is an instance variable.
int rb_is_const_id(ID id)
Classifies the given ID, then sees if it is a constant.
int rb_is_class_id(ID id)
Classifies the given ID, then sees if it is a class variable.
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
VALUE rb_reg_nth_defined(int n, VALUE md)
Identical to rb_reg_nth_match(), except it just returns Boolean.
VALUE rb_str_subseq(VALUE str, rb_len_t beg, rb_len_t len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
VALUE rb_mutex_new(void)
Creates a mutex.
VALUE rb_mutex_locked_p(VALUE mutex)
Queries if there are any threads that holds the lock.
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Obtains the lock, runs the passed function, and releases the lock when it completes.
VALUE rb_exec_recursive_paired(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h)
Identical to rb_exec_recursive(), except it checks for the recursion on the ordered pair of { g,...
VALUE rb_mod_remove_cvar(VALUE mod, VALUE name)
Resembles Module#remove_class_variable.
VALUE rb_obj_instance_variables(VALUE obj)
Resembles Object#instance_variables.
VALUE rb_f_untrace_var(int argc, const VALUE *argv)
Deletes the passed tracer from the passed global variable, or if omitted, deletes everything.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
VALUE rb_const_list(void *)
This is another mysterious API that comes with no documents at all.
VALUE rb_path2class(const char *path)
Resolves a Q::W::E::R-style path string to the actual class it points.
VALUE rb_autoload_p(VALUE space, ID name)
Queries if an autoload is defined at a point.
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_mod_remove_const(VALUE space, VALUE name)
Resembles Module#remove_const.
VALUE rb_class_path_cached(VALUE mod)
Just another name of rb_mod_name.
VALUE rb_f_trace_var(int argc, const VALUE *argv)
Traces a global variable.
void rb_cvar_set(VALUE klass, ID name, VALUE val)
Assigns a value to a class variable.
VALUE rb_cvar_get(VALUE klass, ID name)
Obtains a value from a class variable.
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv)
Resembles Module#constants.
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front)
Identical to rb_cvar_get(), except it takes additional "front" pointer.
VALUE rb_path_to_class(VALUE path)
Identical to rb_path2class(), except it accepts the path as Ruby's string instead of C's.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
void rb_const_set(VALUE space, ID name, VALUE val)
Names a constant.
VALUE rb_autoload_load(VALUE space, ID name)
Kicks the autoload procedure as if it was "touched".
VALUE rb_mod_name(VALUE mod)
Queries the name of a module.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
VALUE rb_const_get_at(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name)
Identical to rb_set_class_path(), except it accepts the name as Ruby's string instead of C's.
void rb_alias_variable(ID dst, ID src)
Aliases a global variable.
void rb_define_class_variable(VALUE, const char *, VALUE)
Just another name of rb_cv_set.
VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name)
Resembles Object#remove_instance_variable.
void * rb_mod_const_of(VALUE, void *)
This is a variant of rb_mod_const_at().
st_index_t rb_ivar_count(VALUE obj)
Number of instance variables defined on an object.
void * rb_mod_const_at(VALUE, void *)
This API is mysterious.
VALUE rb_const_remove(VALUE space, ID name)
Identical to rb_mod_remove_const(), except it takes the name as ID instead of VALUE.
VALUE rb_const_get_from(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
VALUE rb_cv_get(VALUE klass, const char *name)
Identical to rb_cvar_get(), except it accepts C's string instead of ID.
int rb_const_defined_at(VALUE space, ID name)
Identical to rb_const_defined(), except it doesn't look for parent classes.
void rb_cv_set(VALUE klass, const char *name, VALUE val)
Identical to rb_cvar_set(), except it accepts C's string instead of ID.
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv)
Resembles Module#class_variables.
VALUE rb_f_global_variables(void)
Queries the list of global variables.
VALUE rb_cvar_defined(VALUE klass, ID name)
Queries if the given class has the given class variable.
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
int rb_const_defined_from(VALUE space, ID name)
Identical to rb_const_defined(), except it returns false for private constants.
int rb_const_defined(VALUE space, ID name)
Queries if the constant is defined at the namespace.
void rb_free_generic_ivar(VALUE obj)
Frees the list of instance variables.
const char * rb_sourcefile(void)
Resembles __FILE__.
void rb_clear_constant_cache_for_id(ID id)
Clears the inline constant caches associated with a particular ID.
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
VALUE rb_id2sym(ID id)
Allocates an instance of rb_cSymbol that has the given id.
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
ID rb_to_id(VALUE str)
Identical to rb_intern_str(), except it tries to convert the parameter object to an instance of rb_cS...
rb_gvar_setter_t rb_gvar_var_setter
rb_gvar_marker_t rb_gvar_var_marker
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
VALUE rb_gv_get(const char *name)
Obtains a global variable.
void rb_define_variable(const char *name, VALUE *var)
"Shares" a global variable between Ruby and C.
void rb_gvar_marker_t(VALUE *var)
Type that represents a global variable marker function.
void rb_deprecate_constant(VALUE mod, const char *name)
Asserts that the given constant is deprecated.
void rb_gvar_setter_t(VALUE val, ID id, VALUE *data)
Type that represents a global variable setter function.
rb_gvar_setter_t rb_gvar_val_setter
This is the setter function that backs global variables defined from a ruby script.
rb_gvar_marker_t rb_gvar_undef_marker
void rb_define_readonly_variable(const char *name, const VALUE *var)
Identical to rb_define_variable(), except it does not allow Ruby programs to assign values to such gl...
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
rb_gvar_getter_t rb_gvar_undef_getter
VALUE rb_gv_set(const char *name, VALUE val)
Assigns to a global variable.
rb_gvar_marker_t rb_gvar_val_marker
This is the setter function that backs global variables defined from a ruby script.
VALUE rb_gvar_getter_t(ID id, VALUE *data)
Type that represents a global variable getter function.
VALUE rb_iv_get(VALUE obj, const char *name)
Obtains an instance variable.
rb_gvar_setter_t rb_gvar_undef_setter
rb_gvar_getter_t rb_gvar_val_getter
This is the getter function that backs global variables defined from a ruby script.
VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
Assigns to an instance variable.
rb_gvar_getter_t rb_gvar_var_getter
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
#define RB_OBJ_SET_SHAREABLE(obj)
Wrapper of rb_obj_set_shareable().
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
void rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
Iteration over each instance variable of the object.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
#define RARRAY_LEN
Just another name of rb_array_len.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define RBASIC(obj)
Convenient casting macro.
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
#define RUBY_TYPED_FREE_IMMEDIATELY
Macros to see if each corresponding flag is defined.
#define RTYPEDDATA(obj)
Convenient casting macro.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
const char * rb_class2name(VALUE klass)
Queries the name of the passed class.
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
#define RB_NO_KEYWORDS
Do not pass keywords.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Internal header for Ruby Box.
Internal header for Class.
This is the struct that holds necessary info for a struct.
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_lock.
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_initialize.
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_unlock.
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.