14#include "ruby/internal/config.h"
17#include "ccan/list/list.h"
19#include "debug_counter.h"
23#include "internal/class.h"
24#include "internal/compilers.h"
25#include "internal/error.h"
26#include "internal/eval.h"
27#include "internal/hash.h"
28#include "internal/namespace.h"
29#include "internal/object.h"
30#include "internal/gc.h"
31#include "internal/re.h"
32#include "internal/symbol.h"
33#include "internal/thread.h"
34#include "internal/variable.h"
42#include "ractor_core.h"
46#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
48typedef void rb_gvar_compact_t(
void *var);
56static VALUE autoload_features;
61static VALUE autoload_mutex;
63static void check_before_mod_set(
VALUE,
ID,
VALUE,
const char *);
65static VALUE rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility);
68typedef int rb_ivar_foreach_callback_func(
ID key,
VALUE val, st_data_t arg);
69static void rb_field_foreach(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only);
74 rb_global_tbl = rb_id_table_create(0);
75 generic_fields_tbl_ = st_init_numtable();
80 rb_vm_register_global_object(autoload_mutex);
82 autoload_features = rb_ident_hash_new();
84 rb_vm_register_global_object(autoload_features);
88rb_namespace_p(
VALUE obj)
109classname(
VALUE klass,
bool *permanent)
113 VALUE classpath = RCLASS_CLASSPATH(klass);
114 if (classpath == 0)
return Qnil;
116 *permanent = RCLASS_PERMANENT_CLASSPATH_P(klass);
122rb_mod_name0(
VALUE klass,
bool *permanent)
124 return classname(klass, permanent);
139 return classname(mod, &permanent);
144is_constant_path(
VALUE name)
146 const char *path = RSTRING_PTR(name);
150 const char *p = path;
152 if (p >= pend || !*p) {
157 if (p + 2 <= pend && p[0] ==
':' && p[1] ==
':') {
161 const char *pbeg = p;
162 while (p < pend && *p !=
':') p++;
164 if (pbeg == p)
return false;
166 if (rb_enc_symname_type(pbeg, p - pbeg, enc, 0) != ID_CONST) {
183set_sub_temporary_name_recursive(
VALUE mod,
VALUE data,
int recursive)
185 if (recursive)
return Qfalse;
190 name = build_const_path(rb_ary_last(0, 0, args->names), args->last);
192 set_sub_temporary_name_foreach(mod, args, name);
197set_sub_temporary_name_topmost(
VALUE mod,
VALUE data,
int recursive)
199 if (recursive)
return Qfalse;
202 VALUE name = args->names;
206 set_sub_temporary_name_foreach(mod, args, name);
210static enum rb_id_table_iterator_result
211set_sub_temporary_name_i(
ID id,
VALUE val,
void *data)
214 if (rb_namespace_p(val) && !RCLASS_PERMANENT_CLASSPATH_P(val)) {
220 return ID_TABLE_CONTINUE;
226 RCLASS_WRITE_CLASSPATH(mod, name, FALSE);
230 rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
235 rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
236 rb_ary_set_len(args->names, names_len);
297rb_mod_set_temporary_name(
VALUE mod,
VALUE name)
300 if (RCLASS_PERMANENT_CLASSPATH_P(mod)) {
307 set_sub_temporary_name(mod, 0);
314 if (RSTRING_LEN(name) == 0) {
315 rb_raise(rb_eArgError,
"empty class/module name");
318 if (is_constant_path(name)) {
319 rb_raise(rb_eArgError,
"the temporary name must not be a constant path to avoid confusion");
326 set_sub_temporary_name(mod, name);
339 path = rb_sprintf(
"#<Class:%p>", (
void*)obj);
342 path = rb_sprintf(
"#<Module:%p>", (
void*)obj);
345 path = rb_sprintf(
"#<%"PRIsVALUE
":%p>", klass, (
void*)obj);
355rb_tmp_class_path(
VALUE klass,
bool *permanent, fallback_func fallback)
357 VALUE path = classname(klass, permanent);
369 path = rb_tmp_class_path(
RBASIC(klass)->klass, &perm, fallback);
374 return fallback(klass, path);
381 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
399rb_search_class_path(
VALUE klass)
402 return rb_tmp_class_path(klass, &permanent, no_fallback);
411 return rb_fstring(path);
415build_const_path(
VALUE head,
ID tail)
417 return build_const_pathname(head, rb_id2str(tail));
423 bool permanent =
true;
426 if (under == rb_cObject) {
430 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
431 str = build_const_pathname(str, name);
434 RCLASS_SET_CLASSPATH(klass, str, permanent);
449 const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
451 VALUE c = rb_cObject;
453 if (!rb_enc_asciicompat(enc)) {
454 rb_raise(rb_eArgError,
"invalid class path encoding (non ASCII)");
457 pend = path + RSTRING_LEN(pathname);
458 if (path == pend || path[0] ==
'#') {
459 rb_raise(rb_eArgError,
"can't retrieve anonymous class %"PRIsVALUE,
463 while (p < pend && *p !=
':') p++;
465 if (p < pend && p[0] ==
':') {
466 if ((
size_t)(pend - p) < 2 || p[1] !=
':')
goto undefined_class;
471 goto undefined_class;
473 c = rb_const_search(c,
id, TRUE, FALSE, FALSE);
474 if (UNDEF_P(c))
goto undefined_class;
475 if (!rb_namespace_p(c)) {
476 rb_raise(
rb_eTypeError,
"%"PRIsVALUE
" does not refer to class/module",
485 rb_raise(rb_eArgError,
"undefined class/module % "PRIsVALUE,
506 VALUE path = rb_tmp_class_path(
rb_class_real(klass), &permanent, make_temporary_path);
507 if (
NIL_P(path))
return NULL;
508 return RSTRING_PTR(path);
531 rb_gvar_compact_t *compactor;
533 bool namespace_ready;
556static enum rb_id_table_iterator_result
557free_global_entry_i(
VALUE val,
void *arg)
560 entry->var->counter--;
561 if (entry->var->counter == 0) {
562 free_global_variable(entry->var);
565 return ID_TABLE_DELETE;
569rb_free_rb_global_tbl(
void)
571 rb_id_table_foreach_values(rb_global_tbl, free_global_entry_i, 0);
572 rb_id_table_free(rb_global_tbl);
576rb_free_generic_fields_tbl_(
void)
578 st_free_table(generic_fields_tbl_);
582rb_find_global_entry(
ID id)
587 if (!rb_id_table_lookup(rb_global_tbl,
id, &data)) {
595 if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
596 rb_raise(rb_eRactorIsolationError,
"can not access global variables %s from non-main Ractors", rb_id2name(
id));
603rb_gvar_ractor_local(
const char *name)
606 entry->ractor_local =
true;
610rb_gvar_namespace_ready(
const char *name)
613 entry->var->namespace_ready =
true;
617rb_gvar_undef_compactor(
void *var)
631 entry->ractor_local =
false;
637 var->compactor = rb_gvar_undef_compactor;
639 var->block_trace = 0;
641 var->namespace_ready =
false;
642 rb_id_table_insert(rb_global_tbl,
id, (
VALUE)entry);
650 rb_warning(
"global variable '%"PRIsVALUE
"' not initialized", QUOTE_ID(
id));
656rb_gvar_val_compactor(
void *_var)
663 VALUE new = rb_gc_location(obj);
665 var->data = (
void*)
new;
677 var->compactor = rb_gvar_val_compactor;
679 var->data = (
void*)val;
697 var->data = (
void*)val;
704 if (data) rb_gc_mark_movable(data);
710 if (!var)
return Qnil;
723 if (var) rb_gc_mark_maybe(*var);
729 rb_name_error(
id,
"%"PRIsVALUE
" is a read-only variable", QUOTE_ID(
id));
732static enum rb_id_table_iterator_result
733mark_global_entry(
VALUE v,
void *ignored)
739 (*var->marker)(var->data);
742 if (trace->data) rb_gc_mark_maybe(trace->data);
745 return ID_TABLE_CONTINUE;
748#define gc_mark_table(task) \
749 if (rb_global_tbl) { rb_id_table_foreach_values(rb_global_tbl, task##_global_entry, 0); }
752rb_gc_mark_global_tbl(
void)
757static enum rb_id_table_iterator_result
758update_global_entry(
VALUE v,
void *ignored)
763 (*var->compactor)(var);
764 return ID_TABLE_CONTINUE;
768rb_gc_update_global_tbl(
void)
770 gc_mark_table(update);
774global_id(
const char *name)
778 if (name[0] ==
'$')
id = rb_intern(name);
780 size_t len = strlen(name);
784 memcpy(buf+1, name,
len);
785 id = rb_intern2(buf,
len+1);
792find_global_id(
const char *name)
795 size_t len = strlen(name);
797 if (name[0] ==
'$') {
804 memcpy(buf+1, name,
len);
820 ID id = global_id(name);
823 gvar->data = (
void*)var;
875 trace->next = entry->var->trace;
876 trace->func = rb_trace_eval;
879 entry->var->trace = trace;
893 while (trace->next) {
896 trace->next = next->next;
919 if ((entry = rb_find_global_entry(
id)) == NULL) {
920 rb_name_error(
id,
"undefined global variable %"PRIsVALUE
"", QUOTE_ID(
id));
923 trace = entry->var->trace;
934 if (!entry->var->block_trace) remove_trace(entry->var);
939 if (trace->data == cmd) {
941 if (!entry->var->block_trace) remove_trace(entry->var);
962 (*trace->func)(trace->data, data->val);
973 var->block_trace = 0;
984 (*var->setter)(val, entry->id, var->data);
986 if (var->trace && !var->block_trace) {
987 var->block_trace = 1;
988 trace.trace = var->trace;
995#define USE_NAMESPACE_GVAR_TBL(ns,entry) \
996 (NAMESPACE_OPTIONAL_P(ns) && \
997 (!entry || !entry->var->namespace_ready || entry->var->setter != rb_gvar_readonly_setter))
1008 if (USE_NAMESPACE_GVAR_TBL(ns, entry)) {
1009 rb_hash_aset(ns->gvar_tbl,
rb_id2sym(entry->id), val);
1014 retval = rb_gvar_set_entry(entry, val);
1022 return rb_gvar_set(global_id(name), val);
1028 VALUE retval, gvars, key;
1033 if (USE_NAMESPACE_GVAR_TBL(ns, entry)) {
1034 gvars = ns->gvar_tbl;
1036 if (
RTEST(rb_hash_has_key(gvars, key))) {
1037 retval = rb_hash_aref(gvars, key);
1040 retval = (*var->getter)(entry->id, var->data);
1042 retval =
rb_funcall(retval, rb_intern(
"clone"), 0);
1044 rb_hash_aset(gvars, key, retval);
1048 retval = (*var->getter)(entry->id, var->data);
1056 ID id = find_global_id(name);
1059 rb_warning(
"global variable '%s' not initialized", name);
1063 return rb_gvar_get(
id);
1067rb_gvar_defined(
ID id)
1074rb_gvar_getter_function_of(
ID id)
1077 return entry->var->getter;
1081rb_gvar_setter_function_of(
ID id)
1084 return entry->var->setter;
1087static enum rb_id_table_iterator_result
1088gvar_i(
ID key,
VALUE val,
void *a)
1092 return ID_TABLE_CONTINUE;
1101 if (!rb_ractor_main_p()) {
1102 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
1106 rb_id_table_foreach(rb_global_tbl, gvar_i, (
void *)ary);
1107 if (!
NIL_P(backref)) {
1109 int i, nmatch = rb_match_count(backref);
1111 for (i = 1; i <= nmatch; ++i) {
1115 buf[1] = (char)(i +
'0');
1116 sym =
ID2SYM(rb_intern2(buf, 2));
1135 if (!rb_ractor_main_p()) {
1136 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
1140 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
1143 rb_id_table_insert(gtbl, name1, (
VALUE)entry1);
1145 else if ((entry1 = (
struct rb_global_entry *)data1)->var != entry2->var) {
1147 if (var->block_trace) {
1151 if (var->counter == 0) {
1152 free_global_variable(var);
1158 entry2->var->counter++;
1159 entry1->var = entry2->var;
1163IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
ID id)
1165 if (UNLIKELY(!rb_ractor_main_p())) {
1167 rb_raise(rb_eRactorIsolationError,
"can not set instance variables of classes/modules by non-main Ractors");
1172#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
1173 if (UNLIKELY(!rb_ractor_main_p())) { \
1174 rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
1178generic_fields_tbl(
VALUE obj,
ID id,
bool force_check_ractor)
1180 ASSERT_vm_locking();
1184 UNLIKELY(!rb_ractor_main_p()) &&
1187 rb_raise(rb_eRactorIsolationError,
"can not access instance variables of shareable objects from non-main Ractors");
1189 return generic_fields_tbl_;
1193generic_fields_tbl_no_ractor_check(
VALUE obj)
1195 return generic_fields_tbl(obj, 0,
false);
1199rb_generic_fields_tbl_get(
void)
1201 return generic_fields_tbl_;
1214 if (st_lookup(generic_fields_tbl(obj,
id,
false), (st_data_t)obj, &data)) {
1227 return rb_gen_fields_tbl_get(obj, 0, fields_tbl);
1231gen_fields_tbl_bytes(
size_t n)
1241 uint32_t
len = old ? old->as.shape.fields_count : 0;
1244 fields_tbl->as.shape.fields_count = n;
1246 fields_tbl->as.shape.fields[
len] =
Qundef;
1253rb_mark_generic_ivar(
VALUE obj)
1256 if (st_lookup(generic_fields_tbl_no_ractor_check(obj), (st_data_t)obj, &data)) {
1258 if (rb_shape_obj_too_complex_p(obj)) {
1259 rb_mark_tbl_no_pin(fields_tbl->as.complex.table);
1262 for (uint32_t i = 0; i < fields_tbl->as.shape.fields_count; i++) {
1263 rb_gc_mark_movable(fields_tbl->as.shape.fields[i]);
1272 st_data_t key = (st_data_t)obj, value;
1274 bool too_complex = rb_shape_obj_too_complex_p(obj);
1276 if (st_delete(generic_fields_tbl_no_ractor_check(obj), &key, &value)) {
1279 if (UNLIKELY(too_complex)) {
1280 st_free_table(fields_tbl->as.complex.table);
1288rb_generic_ivar_memsize(
VALUE obj)
1292 if (rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {
1293 if (rb_shape_obj_too_complex_p(obj)) {
1294 return sizeof(
struct gen_fields_tbl) + st_memsize(fields_tbl->as.complex.table);
1297 return gen_fields_tbl_bytes(fields_tbl->as.shape.fields_count);
1303#if !SHAPE_IN_BASIC_FLAGS
1305rb_generic_shape_id(
VALUE obj)
1308 shape_id_t shape_id = 0;
1312 st_table* global_iv_table = generic_fields_tbl(obj, 0,
false);
1314 if (global_iv_table && st_lookup(global_iv_table, obj, (st_data_t *)&fields_tbl)) {
1315 shape_id = fields_tbl->shape_id;
1318 shape_id = SPECIAL_CONST_SHAPE_ID;
1333 if (rb_shape_obj_too_complex_p(obj)) {
1334 n = st_table_size(fields_tbl->as.complex.table);
1337 for (i = 0; i < fields_tbl->as.shape.fields_count; i++) {
1338 if (!UNDEF_P(fields_tbl->as.shape.fields[i])) {
1348rb_obj_field_get(
VALUE obj, shape_id_t target_shape_id)
1351 RUBY_ASSERT(RSHAPE(target_shape_id)->
type == SHAPE_IVAR || RSHAPE(target_shape_id)->
type == SHAPE_OBJ_ID);
1353 if (rb_shape_id_too_complex_p(target_shape_id)) {
1358 ASSERT_vm_locking();
1359 fields_hash = RCLASS_FIELDS_HASH(obj);
1362 fields_hash = ROBJECT_FIELDS_HASH(obj);
1367 rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
1369 fields_hash = fields_tbl->as.complex.table;
1373 st_lookup(fields_hash, RSHAPE(target_shape_id)->edge_name, &value);
1378 attr_index_t attr_index = RSHAPE(target_shape_id)->next_field_index - 1;
1383 ASSERT_vm_locking();
1384 fields = RCLASS_PRIME_FIELDS(obj);
1392 rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
1394 fields = fields_tbl->as.shape.fields;
1397 return fields[attr_index];
1405 shape_id_t shape_id;
1409#if SHAPE_IN_BASIC_FLAGS
1410 shape_id = RBASIC_SHAPE_ID(obj);
1422#if !SHAPE_IN_BASIC_FLAGS
1423 shape_id = RCLASS_SHAPE_ID(obj);
1426 if (rb_shape_obj_too_complex_p(obj)) {
1427 st_table * iv_table = RCLASS_FIELDS_HASH(obj);
1428 if (rb_st_lookup(iv_table, (st_data_t)
id, (st_data_t *)&val)) {
1436 attr_index_t index = 0;
1437 shape = RSHAPE(shape_id);
1438 found = rb_shape_get_iv_index(shape,
id, &index);
1441 ivar_list = RCLASS_PRIME_FIELDS(obj);
1444 val = ivar_list[index];
1455 UNLIKELY(!rb_ractor_main_p()) &&
1457 rb_raise(rb_eRactorIsolationError,
1458 "can not get unshareable values from instance variables of classes/modules from non-main Ractors");
1464#if !SHAPE_IN_BASIC_FLAGS
1465 shape_id = ROBJECT_SHAPE_ID(obj);
1467 if (rb_shape_obj_too_complex_p(obj)) {
1468 st_table * iv_table = ROBJECT_FIELDS_HASH(obj);
1470 if (rb_st_lookup(iv_table, (st_data_t)
id, (st_data_t *)&val)) {
1485 rb_gen_fields_tbl_get(obj,
id, &fields_tbl);
1487 if (rb_shape_obj_too_complex_p(obj)) {
1489 if (rb_st_lookup(fields_tbl->as.complex.table, (st_data_t)
id, (st_data_t *)&val)) {
1497#if !SHAPE_IN_BASIC_FLAGS
1498 shape_id = fields_tbl->shape_id;
1500 ivar_list = fields_tbl->as.shape.fields;
1508 attr_index_t index = 0;
1509 shape = RSHAPE(shape_id);
1510 if (rb_shape_get_iv_index(shape,
id, &index)) {
1511 return ivar_list[index];
1520 VALUE iv = rb_ivar_lookup(obj,
id,
Qnil);
1521 RB_DEBUG_COUNTER_INC(ivar_get_base);
1528 return rb_ivar_lookup(obj,
id,
Qnil);
1534 rb_check_frozen(obj);
1538 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1541 if (!rb_shape_transition_remove_ivar(obj,
id, &val)) {
1542 if (!rb_shape_obj_too_complex_p(obj)) {
1543 rb_evict_fields_to_hash(obj);
1550 table = RCLASS_WRITABLE_FIELDS_HASH(obj);
1554 table = ROBJECT_FIELDS_HASH(obj);
1559 if (rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {
1560 table = fields_tbl->as.complex.table;
1567 if (!st_delete(table, (st_data_t *)&
id, (st_data_t *)&val)) {
1577rb_attr_delete(
VALUE obj,
ID id)
1579 return rb_ivar_delete(obj,
id,
Qnil);
1586 shape_id_t shape_id = rb_shape_transition_complex(obj);
1588 VALUE *old_fields = NULL;
1592 if (!(
RBASIC(obj)->flags & ROBJECT_EMBED)) {
1595 rb_shape_set_shape_id(obj, shape_id);
1596 ROBJECT_SET_FIELDS_HASH(obj, table);
1600 old_fields = RCLASS_PRIME_FIELDS(obj);
1601 rb_shape_set_shape_id(obj, shape_id);
1602 RCLASS_SET_FIELDS_HASH(obj, table);
1607 struct st_table *gen_ivs = generic_fields_tbl_no_ractor_check(obj);
1610 st_lookup(gen_ivs, (st_data_t)obj, (st_data_t *)&old_fields_tbl);
1612 if (old_fields_tbl) {
1617#if SHAPE_IN_BASIC_FLAGS
1618 rb_shape_set_shape_id(obj, shape_id);
1620 old_fields_tbl->shape_id = shape_id;
1622 old_fields_tbl->as.complex.table = table;
1623 old_fields = (
VALUE *)old_fields_tbl;
1627 fields_tbl->as.complex.table = table;
1628 st_insert(gen_ivs, (st_data_t)obj, (st_data_t)fields_tbl);
1630#if SHAPE_IN_BASIC_FLAGS
1631 rb_shape_set_shape_id(obj, shape_id);
1633 fields_tbl->shape_id = shape_id;
1647 RUBY_ASSERT(rb_shape_canonical_p(rb_obj_shape(obj)));
1648 RUBY_ASSERT(rb_obj_shape(obj)->next_field_index == 0);
1650 obj_transition_too_complex(obj, table);
1655rb_evict_fields_to_hash(
VALUE obj)
1657 void rb_obj_copy_fields_to_hash_table(
VALUE obj,
st_table *table);
1662 st_table *table = st_init_numtable_with_size(shape->next_field_index);
1663 rb_obj_copy_fields_to_hash_table(obj, table);
1664 obj_transition_too_complex(obj, table);
1670rb_evict_ivars_to_hash(
VALUE obj)
1677 rb_obj_copy_ivs_to_hash_table(obj, table);
1678 obj_transition_too_complex(obj, table);
1689general_ivar_set(
VALUE obj,
ID id,
VALUE val, void *data,
1691 void (*shape_resize_fields_func)(
VALUE, attr_index_t, attr_index_t,
void *),
1692 void (*set_shape_id_func)(
VALUE, shape_id_t,
void *),
1693 void (*transition_too_complex_func)(
VALUE,
void *),
1701 rb_shape_t *current_shape = rb_obj_shape(obj);
1703 if (UNLIKELY(rb_shape_too_complex_p(current_shape))) {
1708 if (!rb_shape_get_iv_index(current_shape,
id, &index)) {
1709 result.existing =
false;
1711 index = current_shape->next_field_index;
1712 if (index >= SHAPE_MAX_FIELDS) {
1713 rb_raise(rb_eArgError,
"too many instance variables");
1716 shape_id_t next_shape_id = rb_shape_transition_add_ivar(obj,
id);
1717 rb_shape_t *next_shape = RSHAPE(next_shape_id);
1718 if (UNLIKELY(rb_shape_too_complex_p(next_shape))) {
1719 transition_too_complex_func(obj, data);
1722 else if (UNLIKELY(next_shape->capacity != current_shape->capacity)) {
1723 RUBY_ASSERT(next_shape->capacity > current_shape->capacity);
1724 shape_resize_fields_func(obj, current_shape->capacity, next_shape->capacity, data);
1728 RUBY_ASSERT(index == (next_shape->next_field_index - 1));
1729 set_shape_id_func(obj, next_shape_id, data);
1732 VALUE *table = shape_fields_func(obj, data);
1735 result.index = index;
1742 st_table *table = too_complex_table_func(obj, data);
1743 result.existing = st_insert(table, (st_data_t)
id, (st_data_t)val);
1751general_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val,
void *data,
1753 void (*shape_resize_fields_func)(
VALUE, attr_index_t, attr_index_t,
void *),
1754 void (*set_shape_id_func)(
VALUE, shape_id_t,
void *),
1755 void (*transition_too_complex_func)(
VALUE,
void *),
1758 rb_shape_t *current_shape = rb_obj_shape(obj);
1760 if (UNLIKELY(rb_shape_id_too_complex_p(target_shape_id))) {
1761 if (UNLIKELY(!rb_shape_too_complex_p(current_shape))) {
1762 transition_too_complex_func(obj, data);
1765 st_table *table = too_complex_table_func(obj, data);
1766 if (RSHAPE(target_shape_id)->next_field_index > current_shape->next_field_index) {
1767 set_shape_id_func(obj, target_shape_id, data);
1770 st_insert(table, (st_data_t)RSHAPE(target_shape_id)->edge_name, (st_data_t)val);
1774 attr_index_t index = RSHAPE(target_shape_id)->next_field_index - 1;
1775 if (index >= current_shape->capacity) {
1776 shape_resize_fields_func(obj, current_shape->capacity, RSHAPE(target_shape_id)->capacity, data);
1779 if (RSHAPE(target_shape_id)->next_field_index > current_shape->next_field_index) {
1780 set_shape_id_func(obj, target_shape_id, data);
1783 VALUE *table = shape_fields_func(obj, data);
1792 shape_id_t shape_id;
1797generic_fields_lookup_ensure_size(st_data_t *k, st_data_t *v, st_data_t u,
int existing)
1799 ASSERT_vm_locking();
1804 if (!existing || fields_lookup->resize) {
1806 RUBY_ASSERT(RSHAPE(fields_lookup->shape_id)->type == SHAPE_IVAR || RSHAPE(fields_lookup->shape_id)->type == SHAPE_OBJ_ID);
1807 RUBY_ASSERT(RSHAPE(RSHAPE(fields_lookup->shape_id)->parent_id)->capacity < RSHAPE(fields_lookup->shape_id)->capacity);
1813 fields_tbl = gen_fields_tbl_resize(fields_tbl, RSHAPE(fields_lookup->shape_id)->capacity);
1814 *v = (st_data_t)fields_tbl;
1819 fields_lookup->fields_tbl = fields_tbl;
1820 if (fields_lookup->shape_id) {
1821#if SHAPE_IN_BASIC_FLAGS
1822 rb_shape_set_shape_id(fields_lookup->obj, fields_lookup->shape_id);
1824 fields_tbl->shape_id = fields_lookup->shape_id;
1832generic_ivar_set_shape_fields(
VALUE obj,
void *data)
1840 st_update(generic_fields_tbl(obj, fields_lookup->id,
false), (st_data_t)obj, generic_fields_lookup_ensure_size, (st_data_t)fields_lookup);
1846 return fields_lookup->fields_tbl->as.shape.fields;
1850generic_ivar_set_shape_resize_fields(
VALUE obj, attr_index_t _old_capa, attr_index_t new_capa,
void *data)
1854 fields_lookup->resize =
true;
1858generic_ivar_set_set_shape_id(
VALUE obj, shape_id_t shape_id,
void *data)
1862 fields_lookup->shape_id = shape_id;
1866generic_ivar_set_transition_too_complex(
VALUE obj,
void *_data)
1868 rb_evict_fields_to_hash(obj);
1873generic_ivar_set_too_complex_table(
VALUE obj,
void *data)
1878 if (!rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {
1880#if !SHAPE_IN_BASIC_FLAGS
1881 fields_tbl->shape_id = rb_shape_transition_complex(obj);
1883 fields_tbl->as.complex.table = st_init_numtable_with_size(1);
1887 st_insert(generic_fields_tbl(obj, fields_lookup->id,
false), (st_data_t)obj, (st_data_t)fields_tbl);
1896 return fields_tbl->as.complex.table;
1908 general_ivar_set(obj,
id, val, &fields_lookup,
1909 generic_ivar_set_shape_fields,
1910 generic_ivar_set_shape_resize_fields,
1911 generic_ivar_set_set_shape_id,
1912 generic_ivar_set_transition_too_complex,
1913 generic_ivar_set_too_complex_table);
1917generic_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val)
1924 general_field_set(obj, target_shape_id, val, &fields_lookup,
1925 generic_ivar_set_shape_fields,
1926 generic_ivar_set_shape_resize_fields,
1927 generic_ivar_set_set_shape_id,
1928 generic_ivar_set_transition_too_complex,
1929 generic_ivar_set_too_complex_table);
1933rb_ensure_iv_list_size(
VALUE obj, uint32_t current_capacity, uint32_t new_capacity)
1937 if (
RBASIC(obj)->flags & ROBJECT_EMBED) {
1942 ROBJECT(obj)->as.heap.fields = newptr;
1950rb_obj_copy_ivs_to_hash_table_i(
ID key,
VALUE val, st_data_t arg)
1954 st_add_direct((
st_table *)arg, (st_data_t)key, (st_data_t)val);
1961 rb_ivar_foreach(obj, rb_obj_copy_ivs_to_hash_table_i, (st_data_t)table);
1967 rb_field_foreach(obj, rb_obj_copy_ivs_to_hash_table_i, (st_data_t)table,
false);
1971obj_ivar_set_shape_fields(
VALUE obj,
void *_data)
1979obj_ivar_set_shape_resize_fields(
VALUE obj, attr_index_t old_capa, attr_index_t new_capa,
void *_data)
1981 rb_ensure_iv_list_size(obj, old_capa, new_capa);
1985obj_ivar_set_set_shape_id(
VALUE obj, shape_id_t shape_id,
void *_data)
1987 rb_shape_set_shape_id(obj, shape_id);
1991obj_ivar_set_transition_too_complex(
VALUE obj,
void *_data)
1993 rb_evict_fields_to_hash(obj);
1997obj_ivar_set_too_complex_table(
VALUE obj,
void *_data)
2001 return ROBJECT_FIELDS_HASH(obj);
2007 return general_ivar_set(obj,
id, val, NULL,
2008 obj_ivar_set_shape_fields,
2009 obj_ivar_set_shape_resize_fields,
2010 obj_ivar_set_set_shape_id,
2011 obj_ivar_set_transition_too_complex,
2012 obj_ivar_set_too_complex_table).index;
2016obj_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val)
2018 general_field_set(obj, target_shape_id, val, NULL,
2019 obj_ivar_set_shape_fields,
2020 obj_ivar_set_shape_resize_fields,
2021 obj_ivar_set_set_shape_id,
2022 obj_ivar_set_transition_too_complex,
2023 obj_ivar_set_too_complex_table);
2033 rb_check_frozen(obj);
2034 rb_obj_ivar_set(obj,
id, val);
2039rb_shape_set_shape_id(
VALUE obj, shape_id_t shape_id)
2041 if (rb_obj_shape_id(obj) == shape_id) {
2045#if SHAPE_IN_BASIC_FLAGS
2046 RBASIC_SET_SHAPE_ID(obj, shape_id);
2050 ROBJECT_SET_SHAPE_ID(obj, shape_id);
2054 RCLASS_SET_SHAPE_ID(obj, shape_id);
2057 if (shape_id != SPECIAL_CONST_SHAPE_ID) {
2061 st_table* global_iv_table = generic_fields_tbl(obj, 0,
false);
2063 if (st_lookup(global_iv_table, obj, (st_data_t *)&fields_tbl)) {
2064 fields_tbl->shape_id = shape_id;
2067 rb_bug(
"Expected shape_id entry in global iv table");
2086 shape_id_t next_shape_id = rb_shape_transition_frozen(x);
2090 if (rb_shape_id_too_complex_p(next_shape_id) && !rb_shape_obj_too_complex_p(x)) {
2091 rb_evict_fields_to_hash(x);
2093 rb_shape_set_shape_id(x, next_shape_id);
2104 RB_DEBUG_COUNTER_INC(ivar_set_base);
2109 rb_obj_ivar_set(obj,
id, val);
2114 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
2115 rb_class_ivar_set(obj,
id, val);
2119 generic_ivar_set(obj,
id, val);
2127 rb_check_frozen(obj);
2128 ivar_set(obj,
id, val);
2138 ivar_set(obj,
id, val);
2141static void class_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val);
2144rb_obj_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val)
2148 obj_field_set(obj, target_shape_id, val);
2152 ASSERT_vm_locking();
2153 class_field_set(obj, target_shape_id, val);
2156 generic_field_set(obj, target_shape_id, val);
2167 if (rb_shape_obj_too_complex_p(obj)) {
2173 table = (
st_table *)RCLASS_FIELDS_HASH(obj);
2177 table = ROBJECT_FIELDS_HASH(obj);
2182 if (rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {
2183 table = fields_tbl->as.complex.table;
2189 if (!table || !rb_st_lookup(table,
id, &idx)) {
2196 return RBOOL(rb_shape_get_iv_index(rb_obj_shape(obj),
id, &index));
2204 rb_ivar_foreach_callback_func *func;
2212iterate_over_shapes_with_callback(
rb_shape_t *shape, rb_ivar_foreach_callback_func *callback,
struct iv_itr_data *itr_data)
2214 switch ((
enum shape_type)shape->type) {
2216 case SHAPE_T_OBJECT:
2219 if (itr_data->ivar_only) {
2220 return iterate_over_shapes_with_callback(RSHAPE(shape->parent_id), callback, itr_data);
2225 if (iterate_over_shapes_with_callback(RSHAPE(shape->parent_id), callback, itr_data)) {
2232 RUBY_ASSERT(!rb_shape_obj_too_complex_p(itr_data->obj));
2237 RUBY_ASSERT(!rb_shape_obj_too_complex_p(itr_data->obj));
2238 iv_list = RCLASS_PRIME_FIELDS(itr_data->obj);
2241 iv_list = itr_data->fields_tbl->as.shape.fields;
2244 VALUE val = iv_list[shape->next_field_index - 1];
2245 if (!UNDEF_P(val)) {
2246 switch (callback(shape->edge_name, val, itr_data->arg)) {
2253 rb_bug(
"unreachable");
2258 return iterate_over_shapes_with_callback(RSHAPE(shape->parent_id), callback, itr_data);
2259 case SHAPE_OBJ_TOO_COMPLEX:
2261 rb_bug(
"Unreachable");
2267each_hash_iv(st_data_t
id, st_data_t val, st_data_t data)
2270 rb_ivar_foreach_callback_func *callback = itr_data->func;
2271 return callback((
ID)
id, (
VALUE)val, itr_data->arg);
2275obj_fields_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2281 .ivar_only = ivar_only,
2285 if (rb_shape_too_complex_p(shape)) {
2286 rb_st_foreach(ROBJECT_FIELDS_HASH(obj), each_hash_iv, (st_data_t)&itr_data);
2289 iterate_over_shapes_with_callback(shape, func, &itr_data);
2294gen_fields_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2298 if (!rb_gen_fields_tbl_get(obj, 0, &fields_tbl))
return;
2302 .fields_tbl = fields_tbl,
2305 .ivar_only = ivar_only,
2308 if (rb_shape_obj_too_complex_p(obj)) {
2309 rb_st_foreach(fields_tbl->as.complex.table, each_hash_iv, (st_data_t)&itr_data);
2312 iterate_over_shapes_with_callback(shape, func, &itr_data);
2317class_fields_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2326 .ivar_only = ivar_only,
2329 if (rb_shape_obj_too_complex_p(obj)) {
2330 rb_st_foreach(RCLASS_WRITABLE_FIELDS_HASH(obj), each_hash_iv, (st_data_t)&itr_data);
2333 iterate_over_shapes_with_callback(shape, func, &itr_data);
2343 rb_check_frozen(dest);
2356 if (rb_gen_fields_tbl_get(obj, 0, &obj_fields_tbl)) {
2357 if (gen_fields_tbl_count(obj, obj_fields_tbl) == 0)
2362 if (rb_shape_too_complex_p(src_shape)) {
2364 st_table *table = st_copy(obj_fields_tbl->as.complex.table);
2365 if (rb_shape_has_object_id(src_shape)) {
2366 st_data_t
id = (st_data_t)ruby_internal_object_id;
2367 st_delete(table, &
id, NULL);
2369 rb_obj_init_too_complex(dest, table);
2374 rb_shape_t *shape_to_set_on_dest = src_shape;
2375 rb_shape_t *initial_shape = rb_obj_shape(dest);
2377 if (!rb_shape_canonical_p(src_shape)) {
2380 shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
2381 if (UNLIKELY(rb_shape_too_complex_p(shape_to_set_on_dest))) {
2382 st_table *table = rb_st_init_numtable_with_size(src_num_ivs);
2383 rb_obj_copy_ivs_to_hash_table(obj, table);
2384 rb_obj_init_too_complex(dest, table);
2390 if (!shape_to_set_on_dest->capacity) {
2391 rb_shape_set_shape(dest, shape_to_set_on_dest);
2396 new_fields_tbl = gen_fields_tbl_resize(0, shape_to_set_on_dest->capacity);
2398 VALUE *src_buf = obj_fields_tbl->as.shape.fields;
2399 VALUE *dest_buf = new_fields_tbl->as.shape.fields;
2401 if (src_shape->next_field_index == shape_to_set_on_dest->next_field_index) {
2403 MEMCPY(dest_buf, src_buf,
VALUE, shape_to_set_on_dest->next_field_index);
2406 for (uint32_t i = 0; i < shape_to_set_on_dest->next_field_index; i++) {
2411 rb_shape_t *dest_shape = shape_to_set_on_dest;
2412 while (src_shape->parent_id != INVALID_SHAPE_ID) {
2413 if (src_shape->type == SHAPE_IVAR) {
2414 while (dest_shape->edge_name != src_shape->edge_name) {
2415 dest_shape = RSHAPE(dest_shape->parent_id);
2418 RB_OBJ_WRITE(dest, &dest_buf[dest_shape->next_field_index - 1], src_buf[src_shape->next_field_index - 1]);
2420 src_shape = RSHAPE(src_shape->parent_id);
2430 generic_fields_tbl_no_ractor_check(dest);
2431 st_insert(generic_fields_tbl_no_ractor_check(obj), (st_data_t)dest, (st_data_t)new_fields_tbl);
2435 rb_shape_set_shape(dest, shape_to_set_on_dest);
2447rb_replace_generic_ivar(
VALUE clone,
VALUE obj)
2453 st_data_t fields_tbl, obj_data = (st_data_t)obj;
2454 if (st_delete(generic_fields_tbl_, &obj_data, &fields_tbl)) {
2457 st_insert(generic_fields_tbl_, (st_data_t)clone, fields_tbl);
2461 rb_bug(
"unreachable");
2468rb_field_foreach(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
bool ivar_only)
2473 obj_fields_each(obj, func, arg, ivar_only);
2477 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
2480 class_fields_each(obj, func, arg, ivar_only);
2486 gen_fields_each(obj, func, arg, ivar_only);
2495 rb_field_foreach(obj, func, arg,
true);
2503 st_index_t iv_count = 0;
2506 iv_count = ROBJECT_FIELDS_COUNT(obj);
2510 iv_count = RCLASS_FIELDS_COUNT(obj);
2516 if (rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {
2517 iv_count = gen_fields_tbl_count(obj, fields_tbl);
2523 if (rb_shape_obj_has_id(obj)) {
2531ivar_i(
ID key,
VALUE v, st_data_t a)
2568#define rb_is_constant_id rb_is_const_id
2569#define rb_is_constant_name rb_is_const_name
2570#define id_for_var(obj, name, part, type) \
2571 id_for_var_message(obj, name, type, "'%1$s' is not allowed as "#part" "#type" variable name")
2572#define id_for_var_message(obj, name, type, message) \
2573 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
2576 int (*valid_id_p)(
ID),
int (*valid_name_p)(
VALUE),
2577 const char *message,
size_t message_len)
2580 VALUE name = *pname;
2582 if (
id ? !valid_id_p(
id) : !valid_name_p(name)) {
2583 rb_name_err_raise_str(rb_fstring_new(message, message_len),
2615 const ID id = id_for_var(obj, name, an, instance);
2619 rb_check_frozen(obj);
2624 if (!UNDEF_P(val))
return val;
2627 rb_name_err_raise(
"instance variable %1$s not defined",
2632NORETURN(
static void uninitialized_constant(
VALUE,
VALUE));
2634uninitialized_constant(
VALUE klass,
VALUE name)
2637 rb_name_err_raise(
"uninitialized constant %2$s::%1$s",
2640 rb_name_err_raise(
"uninitialized constant %1$s",
2647 VALUE value = rb_funcallv(klass, idConst_missing, 1, &name);
2648 rb_vm_inc_const_missing_count();
2697 VALUE ref = ec->private_const_reference;
2698 rb_vm_pop_cfunc_frame();
2700 ec->private_const_reference = 0;
2701 rb_name_err_raise(
"private constant %2$s::%1$s referenced", ref, name);
2703 uninitialized_constant(klass, name);
2709autoload_table_mark(
void *ptr)
2711 rb_mark_tbl_no_pin((
st_table *)ptr);
2715autoload_table_free(
void *ptr)
2721autoload_table_memsize(
const void *ptr)
2724 return st_memsize(tbl);
2728autoload_table_compact(
void *ptr)
2730 rb_gc_ref_update_table_values_only((
st_table *)ptr);
2735 {autoload_table_mark, autoload_table_free, autoload_table_memsize, autoload_table_compact,},
2736 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
2739#define check_autoload_table(av) \
2740 (struct st_table *)rb_check_typeddata((av), &autoload_table_type)
2751 if (RICLASS_IS_ORIGIN_P(mod)) {
2755 mod =
RBASIC(mod)->klass;
2763 VALUE tbl_value = rb_ivar_lookup(mod, autoload,
Qfalse);
2764 if (!
RTEST(tbl_value) || !(tbl = check_autoload_table(tbl_value)) || !st_lookup(tbl, (st_data_t)
id, &val)) {
2774 struct ccan_list_node cnode;
2777 VALUE autoload_data_value;
2793 rb_const_flag_t flag;
2809 rb_serial_t fork_gen;
2812 struct ccan_list_head constants;
2816autoload_data_compact(
void *ptr)
2820 p->feature = rb_gc_location(p->feature);
2821 p->mutex = rb_gc_location(p->mutex);
2825autoload_data_mark(
void *ptr)
2829 rb_gc_mark_movable(p->feature);
2830 rb_gc_mark_movable(p->mutex);
2834autoload_data_free(
void *ptr)
2839 ccan_list_for_each_safe(&p->constants,
autoload_const, next, cnode) {
2847autoload_data_memsize(
const void *ptr)
2854 {autoload_data_mark, autoload_data_free, autoload_data_memsize, autoload_data_compact},
2855 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
2859autoload_const_compact(
void *ptr)
2863 ac->module = rb_gc_location(ac->module);
2864 ac->autoload_data_value = rb_gc_location(ac->autoload_data_value);
2865 ac->value = rb_gc_location(ac->value);
2866 ac->file = rb_gc_location(ac->file);
2867 ac->namespace = rb_gc_location(ac->namespace);
2871autoload_const_mark(
void *ptr)
2875 rb_gc_mark_movable(ac->module);
2876 rb_gc_mark_movable(ac->autoload_data_value);
2877 rb_gc_mark_movable(ac->value);
2878 rb_gc_mark_movable(ac->file);
2879 rb_gc_mark_movable(ac->namespace);
2883autoload_const_memsize(
const void *ptr)
2889autoload_const_free(
void *ptr)
2899 {autoload_const_mark, autoload_const_free, autoload_const_memsize, autoload_const_compact,},
2900 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2904get_autoload_data(
VALUE autoload_const_value,
struct autoload_const **autoload_const_pointer)
2917 if (autoload_const_pointer) *autoload_const_pointer =
autoload_const;
2923 VALUE dst_tbl_value;
2929autoload_copy_table_for_namespace_i(st_data_t key, st_data_t value, st_data_t arg)
2933 struct st_table *tbl = data->dst_tbl;
2934 VALUE tbl_value = data->dst_tbl_value;
2940 VALUE autoload_data_value = src_const->autoload_data_value;
2952 st_insert(tbl, (st_data_t)
autoload_const->name, (st_data_t)new_value);
2961 struct st_table *src_tbl, *dst_tbl;
2962 VALUE src_tbl_value, dst_tbl_value;
2963 if (!rb_st_lookup(iv_ptr, (st_data_t)autoload, (st_data_t *)&src_tbl_value)) {
2967 if (!
RTEST(src_tbl_value) || !(src_tbl = check_autoload_table(src_tbl_value))) {
2971 src_tbl = check_autoload_table(src_tbl_value);
2977 .dst_tbl_value = dst_tbl_value,
2982 st_foreach(src_tbl, autoload_copy_table_for_namespace_i, (st_data_t)&data);
2983 st_insert(iv_ptr, (st_data_t)autoload, (st_data_t)dst_tbl_value);
2987rb_autoload(
VALUE module,
ID name,
const char *feature)
2989 if (!feature || !*feature) {
2990 rb_raise(rb_eArgError,
"empty feature name");
2993 rb_autoload_str(module, name, rb_fstring_cstr(feature));
2997static void const_added(
VALUE klass,
ID const_name);
3007autoload_feature_lookup_or_create(
VALUE feature,
struct autoload_data **autoload_data_pointer)
3009 RUBY_ASSERT_MUTEX_OWNED(autoload_mutex);
3010 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3012 VALUE autoload_data_value = rb_hash_aref(autoload_features, feature);
3015 if (
NIL_P(autoload_data_value)) {
3021 if (autoload_data_pointer) *autoload_data_pointer =
autoload_data;
3023 rb_hash_aset(autoload_features, feature, autoload_data_value);
3025 else if (autoload_data_pointer) {
3026 *autoload_data_pointer =
rb_check_typeddata(autoload_data_value, &autoload_data_type);
3029 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3030 return autoload_data_value;
3034autoload_table_lookup_or_create(
VALUE module)
3036 VALUE autoload_table_value = rb_ivar_lookup(module, autoload,
Qfalse);
3037 if (
RTEST(autoload_table_value)) {
3038 return autoload_table_value;
3042 rb_class_ivar_set(module, autoload, autoload_table_value);
3044 return autoload_table_value;
3049autoload_synchronized(
VALUE _arguments)
3053 rb_const_entry_t *constant_entry = rb_const_lookup(arguments->module, arguments->name);
3054 if (constant_entry && !UNDEF_P(constant_entry->value)) {
3059 const_set(arguments->module, arguments->name,
Qundef);
3061 VALUE autoload_table_value = autoload_table_lookup_or_create(arguments->module);
3062 struct st_table *autoload_table = check_autoload_table(autoload_table_value);
3065 VALUE feature = rb_fstring(arguments->feature);
3068 VALUE autoload_data_value = autoload_feature_lookup_or_create(feature, &
autoload_data);
3080 st_insert(autoload_table, (st_data_t)arguments->name, (st_data_t)autoload_const_value);
3094 rb_raise(
rb_eNameError,
"autoload must be constant name: %"PRIsVALUE
"", QUOTE_ID(name));
3098 if (!RSTRING_LEN(feature)) {
3099 rb_raise(rb_eArgError,
"empty feature name");
3106 .namespace = current_namespace,
3111 if (result ==
Qtrue) {
3112 const_added(module, name);
3117autoload_delete(
VALUE module,
ID name)
3119 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3121 st_data_t load = 0, key = name;
3125 VALUE table_value = rb_ivar_lookup(module, autoload,
Qfalse);
3126 if (
RTEST(table_value)) {
3127 struct st_table *table = check_autoload_table(table_value);
3129 st_delete(table, &key, &load);
3152 if (table->num_entries == 0) {
3153 rb_attr_delete(module, autoload);
3158 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3164 return ele->mutex !=
Qnil && !rb_mutex_owned_p(ele->mutex);
3168check_autoload_required(
VALUE mod,
ID id,
const char **loadingpath)
3172 const char *loading;
3174 if (!autoload_const_value || !(
autoload_data = get_autoload_data(autoload_const_value, 0))) {
3187 return autoload_const_value;
3190 loading = RSTRING_PTR(feature);
3193 return autoload_const_value;
3196 if (loadingpath && loading) {
3197 *loadingpath = loading;
3198 return autoload_const_value;
3207rb_autoloading_value(
VALUE mod,
ID id,
VALUE* value, rb_const_flag_t *flag)
3210 if (!ac)
return FALSE;
3226 return ele->mutex !=
Qnil && rb_mutex_owned_p(ele->mutex);
3233autoloading_const_entry(
VALUE mod,
ID id)
3240 if (!load || !(ele = get_autoload_data(load, &ac))) {
3246 if (autoload_by_current(ele)) {
3247 if (!UNDEF_P(ac->value)) {
3256autoload_defined_p(
VALUE mod,
ID id)
3261 if (!ce || !UNDEF_P(ce->value)) {
3267 return !rb_autoloading_value(mod,
id, NULL, NULL);
3289 check_before_mod_set(ac->module, ac->name, ac->value,
"constant");
3293 const_tbl_update(ac,
true);
3301autoload_load_needed(
VALUE _arguments)
3305 const char *loading = 0, *src;
3307 if (!autoload_defined_p(arguments->module, arguments->name)) {
3311 VALUE autoload_const_value = check_autoload_required(arguments->module, arguments->name, &loading);
3312 if (!autoload_const_value) {
3317 if (src && loading && strcmp(src, loading) == 0) {
3338 return autoload_const_value;
3342autoload_apply_constants(
VALUE _arguments)
3344 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3356 ccan_list_for_each_safe(&arguments->autoload_data->constants,
autoload_const, next, cnode) {
3362 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3374autoload_feature_require_in_builtin(
VALUE arg)
3378 VALUE result =
rb_funcall(data->receiver, rb_intern(
"require"), 1, data->feature);
3379 if (
RTEST(result)) {
3386autoload_feature_require_ensure_in_builtin(
VALUE _arg)
3392 rb_gccct_clear_table(
Qnil);
3393 rb_namespace_disable_builtin();
3398autoload_feature_require_in_builtin_wrap(
VALUE arg)
3400 return rb_ensure(autoload_feature_require_in_builtin, arg,
3401 autoload_feature_require_ensure_in_builtin,
Qnil);
3405autoload_feature_require(
VALUE _arguments)
3407 VALUE receiver = rb_vm_top_self();
3417 if (
NIL_P(autoload_namespace)) {
3418 rb_namespace_enable_builtin();
3425 rb_gccct_clear_table(
Qnil);
3427 .arguments = arguments,
3428 .receiver = receiver,
3429 .feature = arguments->autoload_data->feature,
3431 return rb_namespace_exec(rb_builtin_namespace(), autoload_feature_require_in_builtin_wrap, (
VALUE)&data);
3434 if (
RTEST(autoload_namespace) && NAMESPACE_OPTIONAL_P(rb_get_namespace_t(autoload_namespace))) {
3435 receiver = autoload_namespace;
3438 VALUE result =
rb_funcall(receiver, rb_intern(
"require"), 1, arguments->autoload_data->feature);
3440 if (
RTEST(result)) {
3447autoload_try_load(
VALUE _arguments)
3451 VALUE result = autoload_feature_require(_arguments);
3454 rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name);
3456 if (!ce || UNDEF_P(ce->value)) {
3461 if (arguments->module == rb_cObject) {
3463 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
" but it didn't",
3464 arguments->autoload_data->feature,
3470 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
"::%"PRIsVALUE
" but it didn't",
3471 arguments->autoload_data->feature,
3479 ce->flag |= arguments->flag;
3491 if (!ce || !UNDEF_P(ce->value)) {
3496 if (UNLIKELY(!rb_ractor_main_p())) {
3497 return rb_ractor_autoload_load(module, name);
3507 if (autoload_const_value ==
Qfalse)
return autoload_const_value;
3509 arguments.flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
3526 return rb_autoload_at_p(mod,
id, TRUE);
3530rb_autoload_at_p(
VALUE mod,
ID id,
int recur)
3535 while (!autoload_defined_p(mod,
id)) {
3536 if (!recur)
return Qnil;
3538 if (!mod)
return Qnil;
3540 load = check_autoload_required(mod,
id, 0);
3541 if (!load)
return Qnil;
3542 return (ele = get_autoload_data(load, 0)) ? ele->feature :
Qnil;
3548 if (RB_CONST_DEPRECATED_P(ce) &&
3550 if (klass == rb_cObject) {
3561rb_const_get_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3563 VALUE c = rb_const_search(klass,
id, exclude, recurse, visibility);
3565 if (UNLIKELY(!rb_ractor_main_p())) {
3567 rb_raise(rb_eRactorIsolationError,
"can not access non-shareable objects in constant %"PRIsVALUE
"::%s by non-main Ractor.",
rb_class_path(klass), rb_id2name(
id));
3572 return rb_const_missing(klass,
ID2SYM(
id));
3576rb_const_search_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3578 VALUE value, current;
3579 bool first_iteration =
true;
3581 for (current = klass;
3583 current =
RCLASS_SUPER(current), first_iteration =
false) {
3588 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
3601 while ((ce = rb_const_lookup(tmp,
id))) {
3602 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3603 GET_EC()->private_const_reference = tmp;
3606 rb_const_warn_if_deprecated(ce, tmp,
id);
3608 if (UNDEF_P(value)) {
3610 if (am == tmp)
break;
3612 ac = autoloading_const_entry(tmp,
id);
3613 if (ac)
return ac->value;
3617 if (exclude && tmp == rb_cObject) {
3622 if (!recurse)
break;
3626 GET_EC()->private_const_reference = 0;
3631rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3635 if (klass == rb_cObject) exclude = FALSE;
3636 value = rb_const_search_from(klass,
id, exclude, recurse, visibility);
3637 if (!UNDEF_P(value))
return value;
3638 if (exclude)
return value;
3641 return rb_const_search_from(rb_cObject,
id, FALSE, recurse, visibility);
3647 return rb_const_get_0(klass,
id, TRUE, TRUE, FALSE);
3653 return rb_const_get_0(klass,
id, FALSE, TRUE, FALSE);
3659 return rb_const_get_0(klass,
id, TRUE, FALSE, FALSE);
3663rb_public_const_get_from(
VALUE klass,
ID id)
3665 return rb_const_get_0(klass,
id, TRUE, TRUE, TRUE);
3669rb_public_const_get_at(
VALUE klass,
ID id)
3671 return rb_const_get_0(klass,
id, TRUE, FALSE, TRUE);
3674NORETURN(
static void undefined_constant(
VALUE mod,
VALUE name));
3678 rb_name_err_raise(
"constant %2$s::%1$s not defined",
3683rb_const_location_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3685 while (
RTEST(klass)) {
3688 while ((ce = rb_const_lookup(klass,
id))) {
3689 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3692 if (exclude && klass == rb_cObject) {
3696 if (UNDEF_P(ce->value)) {
3698 if (
RTEST(autoload_const_value)) {
3711 if (!recurse)
break;
3720rb_const_location(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3724 if (klass == rb_cObject) exclude = FALSE;
3725 loc = rb_const_location_from(klass,
id, exclude, recurse, visibility);
3726 if (!
NIL_P(loc))
return loc;
3727 if (exclude)
return loc;
3730 return rb_const_location_from(rb_cObject,
id, FALSE, recurse, visibility);
3734rb_const_source_location(
VALUE klass,
ID id)
3736 return rb_const_location(klass,
id, FALSE, TRUE, FALSE);
3740rb_const_source_location_at(
VALUE klass,
ID id)
3742 return rb_const_location(klass,
id, TRUE, FALSE, FALSE);
3758 const ID id = id_for_var(mod, name, a, constant);
3761 undefined_constant(mod, name);
3774 rb_check_frozen(mod);
3776 ce = rb_const_lookup(mod,
id);
3777 if (!ce || !rb_id_table_delete(RCLASS_WRITABLE_CONST_TBL(mod),
id)) {
3779 rb_name_err_raise(
"cannot remove %2$s::%1$s", mod,
ID2SYM(
id));
3782 undefined_constant(mod,
ID2SYM(
id));
3785 rb_const_warn_if_deprecated(ce, mod,
id);
3791 autoload_delete(mod,
id);
3795 if (ce != const_lookup(RCLASS_PRIME_CONST_TBL(mod),
id)) {
3804cv_i_update(st_data_t *k, st_data_t *v, st_data_t a,
int existing)
3806 if (existing)
return ST_STOP;
3811static enum rb_id_table_iterator_result
3818 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
3820 return ID_TABLE_CONTINUE;
3823static enum rb_id_table_iterator_result
3824rb_local_constants_i(
ID const_name,
VALUE const_value,
void *ary)
3829 return ID_TABLE_CONTINUE;
3833rb_local_constants(
VALUE mod)
3843 rb_id_table_foreach(tbl, rb_local_constants_i, (
void *)ary);
3855 tbl = st_init_numtable();
3857 if (RCLASS_CONST_TBL(mod)) {
3860 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
3875 if (tmp == rb_cObject && mod != rb_cObject)
break;
3881list_i(st_data_t key, st_data_t value,
VALUE ary)
3924 bool inherit =
true;
3932 return rb_local_constants(mod);
3937rb_const_defined_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3946 if ((ce = rb_const_lookup(tmp,
id))) {
3947 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3950 if (UNDEF_P(ce->value) && !check_autoload_required(tmp,
id, 0) &&
3951 !rb_autoloading_value(tmp,
id, NULL, NULL))
3954 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3960 if (!recurse)
break;
3974 return rb_const_defined_0(klass,
id, TRUE, TRUE, FALSE);
3980 return rb_const_defined_0(klass,
id, FALSE, TRUE, FALSE);
3986 return rb_const_defined_0(klass,
id, TRUE, FALSE, FALSE);
3990rb_public_const_defined_from(
VALUE klass,
ID id)
3992 return rb_const_defined_0(klass,
id, TRUE, TRUE, TRUE);
3996check_before_mod_set(
VALUE klass,
ID id,
VALUE val,
const char *dest)
3998 rb_check_frozen(klass);
4001static void set_namespace_path(
VALUE named_namespace,
VALUE name);
4003static enum rb_id_table_iterator_result
4004set_namespace_path_i(
ID id,
VALUE v,
void *payload)
4007 VALUE value = ce->value;
4010 return ID_TABLE_CONTINUE;
4013 bool has_permanent_classpath;
4014 classname(value, &has_permanent_classpath);
4015 if (has_permanent_classpath) {
4016 return ID_TABLE_CONTINUE;
4018 set_namespace_path(value, build_const_path(parental_path,
id));
4020 if (!RCLASS_PERMANENT_CLASSPATH_P(value)) {
4021 RCLASS_WRITE_CLASSPATH(value, 0,
false);
4024 return ID_TABLE_CONTINUE;
4033set_namespace_path(
VALUE named_namespace,
VALUE namespace_path)
4035 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
4039 RCLASS_WRITE_CLASSPATH(named_namespace, namespace_path,
true);
4042 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
4049const_added(
VALUE klass,
ID const_name)
4051 if (GET_VM()->running) {
4053 rb_funcallv(klass, idConst_added, 1, &name);
4063 rb_raise(
rb_eTypeError,
"no class/module to define constant %"PRIsVALUE
"",
4068 rb_raise(rb_eRactorIsolationError,
"can not set constants with non-shareable objects by non-main Ractors");
4071 check_before_mod_set(klass,
id, val,
"constant");
4075 struct rb_id_table *tbl = RCLASS_WRITABLE_CONST_TBL(klass);
4077 tbl = rb_id_table_create(0);
4078 RCLASS_WRITE_CONST_TBL(klass, tbl,
false);
4081 rb_id_table_insert(tbl,
id, (
VALUE)ce);
4082 setup_const_entry(ce, klass, val, CONST_PUBLIC);
4086 .module = klass, .name = id,
4087 .value = val, .flag = CONST_PUBLIC,
4090 ac.file = rb_source_location(&ac.line);
4091 const_tbl_update(&ac,
false);
4100 if (rb_cObject && rb_namespace_p(val)) {
4101 bool val_path_permanent;
4102 VALUE val_path = classname(val, &val_path_permanent);
4103 if (
NIL_P(val_path) || !val_path_permanent) {
4104 if (klass == rb_cObject) {
4105 set_namespace_path(val, rb_id2str(
id));
4108 bool parental_path_permanent;
4109 VALUE parental_path = classname(klass, &parental_path_permanent);
4110 if (
NIL_P(parental_path)) {
4112 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
4114 if (parental_path_permanent && !val_path_permanent) {
4115 set_namespace_path(val, build_const_path(parental_path,
id));
4117 else if (!parental_path_permanent &&
NIL_P(val_path)) {
4118 RCLASS_SET_CLASSPATH(val, build_const_path(parental_path,
id),
false);
4128 const_set(klass,
id, val);
4129 const_added(klass,
id);
4133autoload_data_for_named_constant(
VALUE module,
ID name,
struct autoload_const **autoload_const_pointer)
4136 if (!autoload_data_value)
return 0;
4153 VALUE klass = ac->module;
4154 VALUE val = ac->value;
4156 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4157 rb_const_flag_t visibility = ac->flag;
4160 if (rb_id_table_lookup(tbl,
id, &value)) {
4162 if (UNDEF_P(ce->value)) {
4163 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
4164 VALUE file = ac->file;
4165 int line = ac->line;
4166 struct autoload_data *ele = autoload_data_for_named_constant(klass,
id, &ac);
4168 if (!autoload_force && ele) {
4172 ac->file = rb_source_location(&ac->line);
4176 autoload_delete(klass,
id);
4177 ce->flag = visibility;
4182 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
4186 VALUE name = QUOTE_ID(
id);
4187 visibility = ce->flag;
4188 if (klass == rb_cObject)
4189 rb_warn(
"already initialized constant %"PRIsVALUE
"", name);
4191 rb_warn(
"already initialized constant %"PRIsVALUE
"::%"PRIsVALUE
"",
4193 if (!
NIL_P(ce->file) && ce->line) {
4194 rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
4195 "previous definition of %"PRIsVALUE
" was here", name);
4199 setup_const_entry(ce, klass, val, visibility);
4202 tbl = RCLASS_WRITABLE_CONST_TBL(klass);
4206 rb_id_table_insert(tbl,
id, (
VALUE)ce);
4207 setup_const_entry(ce, klass, val, visibility);
4213 rb_const_flag_t visibility)
4215 ce->flag = visibility;
4217 RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
4223 ID id = rb_intern(name);
4226 rb_warn(
"rb_define_const: invalid name '%s' for constant", name);
4229 rb_vm_register_global_object(val);
4237 rb_define_const(rb_cObject, name, val);
4241set_const_visibility(
VALUE mod,
int argc,
const VALUE *argv,
4242 rb_const_flag_t flag, rb_const_flag_t mask)
4250 rb_warning(
"%"PRIsVALUE
" with no argument is just ignored",
4251 QUOTE_ID(rb_frame_callee()));
4255 for (i = 0; i < argc; i++) {
4257 VALUE val = argv[i];
4260 undefined_constant(mod, val);
4262 if ((ce = rb_const_lookup(mod,
id))) {
4265 if (UNDEF_P(ce->value)) {
4268 ele = autoload_data_for_named_constant(mod,
id, &ac);
4277 undefined_constant(mod,
ID2SYM(
id));
4287 long len = strlen(name);
4291 undefined_constant(mod, rb_fstring_new(name,
len));
4293 if (!(ce = rb_const_lookup(mod,
id))) {
4294 undefined_constant(mod,
ID2SYM(
id));
4296 ce->flag |= CONST_DEPRECATED;
4307rb_mod_private_constant(
int argc,
const VALUE *argv,
VALUE obj)
4309 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
4321rb_mod_public_constant(
int argc,
const VALUE *argv,
VALUE obj)
4323 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
4347rb_mod_deprecate_constant(
int argc,
const VALUE *argv,
VALUE obj)
4349 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
4354original_module(
VALUE c)
4362cvar_lookup_at(
VALUE klass,
ID id, st_data_t *v)
4365 if (RICLASS_IS_ORIGIN_P(klass)) {
4370 klass =
RBASIC(klass)->klass;
4375 if (UNDEF_P(n))
return 0;
4382cvar_front_klass(
VALUE klass)
4384 if (RCLASS_SINGLETON_P(klass)) {
4385 VALUE obj = RCLASS_ATTACHED_OBJECT(klass);
4386 if (rb_namespace_p(obj)) {
4396 if (front && target != front) {
4397 if (original_module(front) != original_module(target)) {
4399 "class variable % "PRIsVALUE
" of %"PRIsVALUE
" is overtaken by %"PRIsVALUE
"",
4404 rb_ivar_delete(front,
id,
Qundef);
4409#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
4410 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
4411 if (cvar_lookup_at(klass, id, (v))) { \
4416#define CVAR_LOOKUP(v,r) do {\
4417 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
4418 if (cvar_lookup_at(klass, id, (v))) {r;}\
4419 CVAR_FOREACH_ANCESTORS(klass, v, r);\
4437check_for_cvar_table(
VALUE subclass,
VALUE key)
4441 RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
4442 ruby_vm_global_cvar_state++;
4446 rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
4452 VALUE tmp, front = 0, target = 0;
4455 CVAR_LOOKUP(0, {
if (!front) front = klass; target = klass;});
4457 cvar_overtaken(front, target,
id);
4464 target =
RBASIC(target)->klass;
4466 check_before_mod_set(target,
id, val,
"class variable");
4468 int result = rb_class_ivar_set(target,
id, val);
4470 struct rb_id_table *rb_cvc_tbl = RCLASS_WRITABLE_CVC_TBL(target);
4473 rb_cvc_tbl = rb_id_table_create(2);
4474 RCLASS_WRITE_CVC_TBL(target, rb_cvc_tbl);
4480 if (!rb_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
4482 ent->class_value = target;
4483 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
4485 rb_id_table_insert(rb_cvc_tbl,
id, (
VALUE)ent);
4486 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
4489 ent = (
void *)ent_data;
4490 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
4498 if (RCLASS_SUBCLASSES_FIRST(target)) {
4499 rb_class_foreach_subclass(target, check_for_cvar_table,
id);
4511 value = find_cvar(klass, front, &target,
id);
4513 rb_name_err_raise(
"uninitialized class variable %1$s in %2$s",
4516 cvar_overtaken(*front, target,
id);
4517 return (
VALUE)value;
4530 if (!klass)
return Qfalse;
4531 CVAR_LOOKUP(0,
return Qtrue);
4536cv_intern(
VALUE klass,
const char *name)
4538 ID id = rb_intern(name);
4540 rb_name_err_raise(
"wrong class variable name %1$s",
4549 ID id = cv_intern(klass, name);
4556 ID id = cv_intern(klass, name);
4567cv_i(
ID key,
VALUE v, st_data_t a)
4572 st_update(tbl, (st_data_t)key, cv_i_update, 0);
4578mod_cvar_at(
VALUE mod,
void *data)
4582 tbl = st_init_numtable();
4584 mod = original_module(mod);
4591mod_cvar_of(
VALUE mod,
void *data)
4594 if (RCLASS_SINGLETON_P(mod)) {
4595 if (rb_namespace_p(RCLASS_ATTACHED_OBJECT(mod))) {
4596 data = mod_cvar_at(tmp, data);
4597 tmp = cvar_front_klass(tmp);
4601 data = mod_cvar_at(tmp, data);
4609cv_list_i(st_data_t key, st_data_t value,
VALUE ary)
4617cvar_list(
void *data)
4653 bool inherit =
true;
4658 tbl = mod_cvar_of(mod, 0);
4661 tbl = mod_cvar_at(mod, 0);
4663 return cvar_list(tbl);
4688 const ID id = id_for_var_message(mod, name,
class,
"wrong class variable name %1$s");
4694 rb_check_frozen(mod);
4695 val = rb_ivar_delete(mod,
id,
Qundef);
4696 if (!UNDEF_P(val)) {
4700 rb_name_err_raise(
"cannot remove %1$s for %2$s", mod,
ID2SYM(
id));
4703 rb_name_err_raise(
"class variable %1$s not defined for %2$s",
4722 ID id = rb_intern(name);
4728class_ivar_set_shape_fields(
VALUE obj,
void *_data)
4732 return RCLASS_PRIME_FIELDS(obj);
4736class_ivar_set_shape_resize_fields(
VALUE obj, attr_index_t _old_capa, attr_index_t new_capa,
void *_data)
4742class_ivar_set_set_shape_id(
VALUE obj, shape_id_t shape_id,
void *_data)
4744 rb_shape_set_shape_id(obj, shape_id);
4748class_ivar_set_transition_too_complex(
VALUE obj,
void *_data)
4750 rb_evict_fields_to_hash(obj);
4754class_ivar_set_too_complex_table(
VALUE obj,
void *_data)
4758 return RCLASS_WRITABLE_FIELDS_HASH(obj);
4765 bool existing =
false;
4766 rb_check_frozen(obj);
4768 rb_class_ensure_writable(obj);
4772 existing = general_ivar_set(obj,
id, val, NULL,
4773 class_ivar_set_shape_fields,
4774 class_ivar_set_shape_resize_fields,
4775 class_ivar_set_set_shape_id,
4776 class_ivar_set_transition_too_complex,
4777 class_ivar_set_too_complex_table).existing;
4785class_field_set(
VALUE obj, shape_id_t target_shape_id,
VALUE val)
4788 general_field_set(obj, target_shape_id, val, NULL,
4789 class_ivar_set_shape_fields,
4790 class_ivar_set_shape_resize_fields,
4791 class_ivar_set_set_shape_id,
4792 class_ivar_set_transition_too_complex,
4793 class_ivar_set_too_complex_table);
4797tbl_copy_i(
ID key,
VALUE val, st_data_t dest)
4799 rb_class_ivar_set((
VALUE)dest, key, val);
4824 r = rb_id_table_lookup(tbl,
id, &val);
4834rb_const_lookup(
VALUE klass,
ID id)
4836 return const_lookup(RCLASS_CONST_TBL(klass),
id);
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#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 x)
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 FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define FL_EXIVAR
Old name of RUBY_FL_EXIVAR.
#define FL_USER3
Old name of RUBY_FL_USER3.
#define REALLOC_N
Old name of RB_REALLOC_N.
#define ALLOC
Old name of RB_ALLOC.
#define T_STRING
Old name of RUBY_T_STRING.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define xrealloc
Old name of ruby_xrealloc.
#define ID2SYM
Old name of RB_ID2SYM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define xmalloc
Old name of ruby_xmalloc.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define FL_SET
Old name of RB_FL_SET.
#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 FL_TEST
Old name of RB_FL_TEST.
#define FL_UNSET
Old name of RB_FL_UNSET.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#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_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.
ID rb_check_id_cstr(const char *ptr, long 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_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_hidden_new(long 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_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
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_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.
VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
This API is practically a variant of rb_proc_call_kw() now.
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
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.
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 len
Length of the buffer.
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
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 ROBJECT(obj)
Convenient casting macro.
static VALUE * ROBJECT_FIELDS(VALUE obj)
Queries the instance variables.
#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 RTYPEDDATA_DATA(v)
Convenient getter macro.
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#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.
This is the struct that holds necessary info for a struct.
Internal header for Namespace.
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.