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/object.h"
29#include "internal/re.h"
30#include "internal/symbol.h"
31#include "internal/thread.h"
32#include "internal/variable.h"
36#include "transient_heap.h"
40#include "ractor_core.h"
44#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
46typedef void rb_gvar_compact_t(
void *var);
49static ID autoload, classpath, tmp_classpath;
54static VALUE autoload_features;
59static VALUE autoload_mutex;
61static void check_before_mod_set(
VALUE,
ID,
VALUE,
const char *);
63static VALUE rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility);
70#if !SHAPE_IN_BASIC_FLAGS
78 rb_global_tbl = rb_id_table_create(0);
79 generic_iv_tbl_ = st_init_numtable();
80 autoload = rb_intern_const(
"__autoload__");
82 classpath = rb_intern_const(
"__classpath__");
84 tmp_classpath = rb_intern_const(
"__tmp_classpath__");
88 rb_gc_register_mark_object(autoload_mutex);
90 autoload_features = rb_ident_hash_new();
92 rb_gc_register_mark_object(autoload_features);
96rb_namespace_p(
VALUE obj)
98 if (RB_SPECIAL_CONST_P(obj))
return false;
99 switch (RB_BUILTIN_TYPE(obj)) {
115classname(
VALUE klass,
int *permanent)
118 if (!RCLASS_EXT(klass))
return Qnil;
120 VALUE classpathv = rb_ivar_lookup(klass, classpath,
Qnil);
121 if (
RTEST(classpathv)) {
126 return rb_ivar_lookup(klass, tmp_classpath,
Qnil);;
140 return classname(mod, &permanent);
152 path =
rb_sprintf(
"#<Module:%p>", (
void*)obj);
155 path =
rb_sprintf(
"#<%"PRIsVALUE
":%p>", klass, (
void*)obj);
165rb_tmp_class_path(
VALUE klass,
int *permanent, fallback_func fallback)
167 VALUE path = classname(klass, permanent);
179 path = rb_tmp_class_path(
RBASIC(klass)->klass, &perm, fallback);
183 return fallback(klass, path);
191 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
209rb_search_class_path(
VALUE klass)
212 return rb_tmp_class_path(klass, &permanent, no_fallback);
221 return rb_fstring(path);
225build_const_path(
VALUE head,
ID tail)
227 return build_const_pathname(head, rb_id2str(tail));
234 ID pathid = classpath;
241 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
242 str = build_const_pathname(str, name);
244 pathid = tmp_classpath;
262 const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
266 if (!rb_enc_asciicompat(enc)) {
270 pend = path + RSTRING_LEN(pathname);
271 if (path == pend || path[0] ==
'#') {
276 while (p < pend && *p !=
':') p++;
278 if (p < pend && p[0] ==
':') {
279 if ((
size_t)(pend - p) < 2 || p[1] !=
':')
goto undefined_class;
284 goto undefined_class;
286 c = rb_const_search(c,
id, TRUE, FALSE, FALSE);
287 if (UNDEF_P(c))
goto undefined_class;
288 if (!rb_namespace_p(c)) {
319 VALUE path = rb_tmp_class_path(
rb_class_real(klass), &permanent, make_temporary_path);
320 if (
NIL_P(path))
return NULL;
321 return RSTRING_PTR(path);
344 rb_gvar_compact_t *compactor;
355rb_find_global_entry(
ID id)
360 if (!rb_id_table_lookup(rb_global_tbl,
id, &data)) {
368 if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
369 rb_raise(rb_eRactorIsolationError,
"can not access global variables %s from non-main Ractors",
rb_id2name(
id));
376rb_gvar_ractor_local(
const char *name)
379 entry->ractor_local =
true;
383rb_gvar_undef_compactor(
void *var)
397 entry->ractor_local =
false;
403 var->compactor = rb_gvar_undef_compactor;
405 var->block_trace = 0;
407 rb_id_table_insert(rb_global_tbl,
id, (
VALUE)entry);
415 rb_warning(
"global variable `%"PRIsVALUE
"' not initialized", QUOTE_ID(
id));
421rb_gvar_val_compactor(
void *_var)
428 VALUE new = rb_gc_location(obj);
430 var->data = (
void*)
new;
442 var->compactor = rb_gvar_val_compactor;
444 var->data = (
void*)val;
462 var->data = (
void*)val;
469 if (data) rb_gc_mark_movable(data);
475 if (!var)
return Qnil;
488 if (var) rb_gc_mark_maybe(*var);
494 rb_name_error(
id,
"%"PRIsVALUE
" is a read-only variable", QUOTE_ID(
id));
497static enum rb_id_table_iterator_result
498mark_global_entry(
VALUE v,
void *ignored)
504 (*var->marker)(var->data);
507 if (trace->data) rb_gc_mark_maybe(trace->data);
510 return ID_TABLE_CONTINUE;
514rb_gc_mark_global_tbl(
void)
517 rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
521static enum rb_id_table_iterator_result
522update_global_entry(
VALUE v,
void *ignored)
527 (*var->compactor)(var);
528 return ID_TABLE_CONTINUE;
532rb_gc_update_global_tbl(
void)
535 rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
540global_id(
const char *name)
544 if (name[0] ==
'$')
id = rb_intern(name);
546 size_t len = strlen(name);
548 char *buf =
ALLOCV_N(
char, vbuf, len+1);
550 memcpy(buf+1, name, len);
558find_global_id(
const char *name)
561 size_t len = strlen(name);
563 if (name[0] ==
'$') {
568 char *buf =
ALLOCV_N(
char, vbuf, len+1);
570 memcpy(buf+1, name, len);
586 ID id = global_id(name);
589 gvar->data = (
void*)var;
633 if (rb_scan_args(argc, argv,
"11", &var, &cmd) == 1) {
641 trace->next = entry->var->trace;
642 trace->func = rb_trace_eval;
645 entry->var->trace = trace;
659 while (trace->next) {
662 trace->next = next->next;
680 rb_scan_args(argc, argv,
"11", &var, &cmd);
685 if ((entry = rb_find_global_entry(
id)) == NULL) {
686 rb_name_error(
id,
"undefined global variable %"PRIsVALUE
"", QUOTE_ID(
id));
689 trace = entry->var->trace;
691 VALUE ary = rb_ary_new();
695 rb_ary_push(ary, (
VALUE)trace->data);
700 if (!entry->var->block_trace) remove_trace(entry->var);
705 if (trace->data == cmd) {
707 if (!entry->var->block_trace) remove_trace(entry->var);
728 (*trace->func)(trace->data, data->val);
739 var->block_trace = 0;
750 (*var->setter)(val, entry->id, var->data);
752 if (var->trace && !var->block_trace) {
753 var->block_trace = 1;
754 trace.trace = var->trace;
767 return rb_gvar_set_entry(entry, val);
773 return rb_gvar_set(global_id(name), val);
781 return (*var->getter)(entry->id, var->data);
787 ID id = find_global_id(name);
790 rb_warning(
"global variable `%s' not initialized", name);
794 return rb_gvar_get(
id);
797MJIT_FUNC_EXPORTED
VALUE
798rb_gvar_defined(
ID id)
805rb_gvar_getter_function_of(
ID id)
808 return entry->var->getter;
812rb_gvar_setter_function_of(
ID id)
815 return entry->var->setter;
818static enum rb_id_table_iterator_result
819gvar_i(
ID key,
VALUE val,
void *a)
822 rb_ary_push(ary,
ID2SYM(key));
823 return ID_TABLE_CONTINUE;
829 VALUE ary = rb_ary_new();
832 if (!rb_ractor_main_p()) {
833 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
836 rb_id_table_foreach(rb_global_tbl, gvar_i, (
void *)ary);
837 if (!
NIL_P(backref)) {
839 int i, nmatch = rb_match_count(backref);
841 for (i = 1; i <= nmatch; ++i) {
842 if (!rb_match_nth_defined(i, backref))
continue;
845 buf[1] = (char)(i +
'0');
852 rb_ary_push(ary, sym);
865 if (!rb_ractor_main_p()) {
866 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
870 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
873 rb_id_table_insert(gtbl, name1, (
VALUE)entry1);
875 else if ((entry1 = (
struct rb_global_entry *)data1)->var != entry2->var) {
877 if (var->block_trace) {
881 if (var->counter == 0) {
894 entry2->var->counter++;
895 entry1->var = entry2->var;
899IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
ID id)
901 if (UNLIKELY(!rb_ractor_main_p())) {
903 rb_raise(rb_eRactorIsolationError,
"can not set instance variables of classes/modules by non-main Ractors");
908#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
909 if (UNLIKELY(!rb_ractor_main_p())) { \
910 rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
914generic_ivtbl(
VALUE obj,
ID id,
bool force_check_ractor)
919 !RB_OBJ_FROZEN_RAW(obj) &&
920 UNLIKELY(!rb_ractor_main_p()) &&
923 rb_raise(rb_eRactorIsolationError,
"can not access instance variables of shareable objects from non-main Ractors");
925 return generic_iv_tbl_;
929generic_ivtbl_no_ractor_check(
VALUE obj)
931 return generic_ivtbl(obj, 0,
false);
939 if (st_lookup(generic_ivtbl(obj,
id,
false), (st_data_t)obj, &data)) {
947MJIT_FUNC_EXPORTED
int
957 if (st_lookup(generic_ivtbl(obj,
id,
false), (st_data_t)obj, &data)) {
967MJIT_FUNC_EXPORTED
int
970 return rb_gen_ivtbl_get(obj, 0, ivtbl);
974gen_ivtbl_bytes(
size_t n)
980gen_ivtbl_resize(
struct gen_ivtbl *old, uint32_t n)
984 uint32_t len = old ? old->numiv : 0;
988 for (; len < n; len++) {
989 ivtbl->ivptr[len] =
Qundef;
997gen_ivtbl_dup(
const struct gen_ivtbl *orig)
999 size_t s = gen_ivtbl_bytes(orig->numiv);
1002 memcpy(ivtbl, orig, s);
1009generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u,
int existing)
1011 ASSERT_vm_locking();
1018 if (ivup->iv_index < ivtbl->numiv) {
1019 ivup->ivtbl = ivtbl;
1024 ivtbl = gen_ivtbl_resize(ivtbl, ivup->max_index);
1026 *v = (st_data_t)ivtbl;
1027 ivup->ivtbl = ivtbl;
1028#if !SHAPE_IN_BASIC_FLAGS
1029 ivtbl->shape_id = rb_shape_id(ivup->shape);
1035gen_ivtbl_mark(
const struct gen_ivtbl *ivtbl)
1039 for (i = 0; i < ivtbl->numiv; i++) {
1040 rb_gc_mark(ivtbl->ivptr[i]);
1045rb_mark_generic_ivar(
VALUE obj)
1049 if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
1050 gen_ivtbl_mark(ivtbl);
1057 st_data_t key = (st_data_t)rsrc;
1060 if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl))
1061 st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl);
1067 st_data_t key = (st_data_t)obj, ivtbl;
1069 if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, &ivtbl))
1073RUBY_FUNC_EXPORTED
size_t
1074rb_generic_ivar_memsize(
VALUE obj)
1078 if (rb_gen_ivtbl_get(obj, 0, &ivtbl))
1079 return gen_ivtbl_bytes(ivtbl->numiv);
1083#if !SHAPE_IN_BASIC_FLAGS
1084MJIT_FUNC_EXPORTED shape_id_t
1085rb_generic_shape_id(
VALUE obj)
1088 shape_id_t shape_id = 0;
1092 st_table* global_iv_table = generic_ivtbl(obj, 0,
false);
1094 if (global_iv_table && st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
1095 shape_id = ivtbl->shape_id;
1098 shape_id = SPECIAL_CONST_SHAPE_ID;
1108gen_ivtbl_count(
const struct gen_ivtbl *ivtbl)
1113 for (i = 0; i < ivtbl->numiv; i++) {
1114 if (!UNDEF_P(ivtbl->ivptr[i])) {
1127 shape_id_t shape_id;
1131#if SHAPE_IN_BASIC_FLAGS
1132 shape_id = RBASIC_SHAPE_ID(obj);
1144#if !SHAPE_IN_BASIC_FLAGS
1145 shape_id = RCLASS_SHAPE_ID(obj);
1148 attr_index_t index = 0;
1149 shape = rb_shape_get_shape_by_id(shape_id);
1150 found = rb_shape_get_iv_index(shape,
id, &index);
1153 ivar_list = RCLASS_IVPTR(obj);
1156 val = ivar_list[index];
1166 UNLIKELY(!rb_ractor_main_p()) &&
1169 "can not get unshareable values from instance variables of classes/modules from non-main Ractors");
1175#if !SHAPE_IN_BASIC_FLAGS
1176 shape_id = ROBJECT_SHAPE_ID(obj);
1178 if (rb_shape_obj_too_complex(obj)) {
1179 struct rb_id_table * iv_table = ROBJECT_IV_HASH(obj);
1181 if (rb_id_table_lookup(iv_table,
id, &val)) {
1190 ivar_list = ROBJECT_IVPTR(obj);
1196 rb_gen_ivtbl_get(obj,
id, &ivtbl);
1197#if !SHAPE_IN_BASIC_FLAGS
1198 shape_id = ivtbl->shape_id;
1200 ivar_list = ivtbl->ivptr;
1208 attr_index_t index = 0;
1209 shape = rb_shape_get_shape_by_id(shape_id);
1210 if (rb_shape_get_iv_index(shape,
id, &index)) {
1211 return ivar_list[index];
1220 VALUE iv = rb_ivar_lookup(obj,
id,
Qnil);
1221 RB_DEBUG_COUNTER_INC(ivar_get_base);
1228 return rb_ivar_lookup(obj,
id,
Qnil);
1237 rb_shape_t * shape = rb_shape_get_shape(obj);
1242 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1246 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
1252 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
1257 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
1267rb_attr_delete(
VALUE obj,
ID id)
1269 return rb_ivar_delete(obj,
id,
Qnil);
1280 bool found = rb_shape_get_iv_index(shape,
id, &index);
1282 index = shape->next_iv_index;
1283 shape = rb_shape_get_next(shape, obj,
id);
1287 ivup.max_index = shape->next_iv_index;
1288#if !SHAPE_IN_BASIC_FLAGS
1294 ivup.iv_index = (uint32_t)index;
1296 st_update(generic_ivtbl(obj,
id,
false), (st_data_t)obj, generic_ivar_update, (st_data_t)&ivup);
1300 ivup.ivtbl->ivptr[ivup.iv_index] = val;
1304 rb_shape_set_shape(obj, shape);
1309obj_ivar_heap_alloc(
VALUE obj,
size_t newsize)
1311 VALUE *newptr = rb_transient_heap_alloc(obj,
sizeof(
VALUE) * newsize);
1313 if (newptr != NULL) {
1314 ROBJ_TRANSIENT_SET(obj);
1317 ROBJ_TRANSIENT_UNSET(obj);
1324obj_ivar_heap_realloc(
VALUE obj, int32_t len,
size_t newsize)
1329 if (ROBJ_TRANSIENT_P(obj)) {
1331 newptr = obj_ivar_heap_alloc(obj, newsize);
1334 ROBJECT(obj)->as.heap.ivptr = newptr;
1335 for (i=0; i<(int)len; i++) {
1336 newptr[i] = orig_ptr[i];
1341 newptr =
ROBJECT(obj)->as.heap.ivptr;
1347#if USE_TRANSIENT_HEAP
1349rb_obj_transient_heap_evacuate(
VALUE obj,
int promote)
1351 if (ROBJ_TRANSIENT_P(obj)) {
1352 assert(!RB_FL_TEST_RAW(obj, ROBJECT_EMBED));
1354 uint32_t len = ROBJECT_IV_CAPACITY(obj);
1356 const VALUE *old_ptr = ROBJECT_IVPTR(obj);
1361 ROBJ_TRANSIENT_UNSET(obj);
1364 new_ptr = obj_ivar_heap_alloc(obj, len);
1367 ROBJECT(obj)->as.heap.ivptr = new_ptr;
1373rb_ensure_iv_list_size(
VALUE obj, uint32_t current_capacity, uint32_t new_capacity)
1376 VALUE *ptr = ROBJECT_IVPTR(obj);
1379 if (
RBASIC(obj)->flags & ROBJECT_EMBED) {
1380 newptr = obj_ivar_heap_alloc(obj, new_capacity);
1382 RB_FL_UNSET_RAW(obj, ROBJECT_EMBED);
1383 ROBJECT(obj)->as.heap.ivptr = newptr;
1386 newptr = obj_ivar_heap_realloc(obj, current_capacity, new_capacity);
1391rb_ensure_generic_iv_list_size(
VALUE obj,
rb_shape_t *shape, uint32_t newsize)
1397 if (UNLIKELY(!gen_ivtbl_get_unlocked(obj, 0, &ivtbl) || newsize > ivtbl->numiv)) {
1399 .iv_index = newsize - 1,
1400 .max_index = newsize,
1401#if !SHAPE_IN_BASIC_FLAGS
1405 st_update(generic_ivtbl_no_ractor_check(obj), (st_data_t)obj, generic_ivar_update, (st_data_t)&ivup);
1419rb_grow_iv_list(
VALUE obj)
1421 rb_shape_t * initial_shape = rb_shape_get_shape(obj);
1422 uint32_t len = initial_shape->capacity;
1424 uint32_t newsize = (uint32_t)(len * 2);
1426 rb_shape_t * res = rb_shape_transition_shape_capa(initial_shape, newsize);
1428 rb_ensure_iv_list_size(obj, len, newsize);
1430 rb_shape_set_shape(obj, res);
1436rb_obj_evacuate_ivs_to_hash_table(
ID key,
VALUE val, st_data_t arg)
1438 rb_id_table_insert((
struct rb_id_table *)arg, key, val);
1448 uint32_t num_iv = shape->capacity;
1450 if (rb_shape_obj_too_complex(obj)) {
1451 struct rb_id_table * table = ROBJECT_IV_HASH(obj);
1452 rb_id_table_insert(table,
id, val);
1457 if (!rb_shape_get_iv_index(shape,
id, &index)) {
1458 index = shape->next_iv_index;
1459 if (index >= MAX_IVARS) {
1465 if (UNLIKELY(shape->next_iv_index >= num_iv)) {
1468 shape = rb_grow_iv_list(obj);
1469 RUBY_ASSERT(shape->type == SHAPE_CAPACITY_CHANGE);
1472 rb_shape_t *next_shape = rb_shape_get_next(shape, obj,
id);
1474 if (next_shape->type == SHAPE_OBJ_TOO_COMPLEX) {
1475 struct rb_id_table * table = rb_id_table_create(shape->next_iv_index);
1478 rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table);
1481 rb_id_table_insert(table,
id, val);
1484 rb_shape_set_too_complex(obj);
1487 if (ROBJ_TRANSIENT_P(obj)) {
1488 ROBJ_TRANSIENT_UNSET(obj);
1490 else if (!(
RBASIC(obj)->flags & ROBJECT_EMBED)) {
1499 rb_shape_set_shape(obj, next_shape);
1501 RUBY_ASSERT(index == (next_shape->next_iv_index - 1));
1519 rb_obj_ivar_set(obj,
id, val);
1524rb_shape_set_shape_id(
VALUE obj, shape_id_t shape_id)
1526 if (rb_shape_get_shape_id(obj) == shape_id) {
1530#if SHAPE_IN_BASIC_FLAGS
1531 RBASIC_SET_SHAPE_ID(obj, shape_id);
1535 ROBJECT_SET_SHAPE_ID(obj, shape_id);
1539 RCLASS_EXT(obj)->shape_id = shape_id;
1542 if (shape_id != SPECIAL_CONST_SHAPE_ID) {
1546 st_table* global_iv_table = generic_ivtbl(obj, 0,
false);
1548 if (st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
1549 ivtbl->shape_id = shape_id;
1552 rb_bug(
"Expected shape_id entry in global iv table");
1571 if (RB_FL_ABLE(x)) {
1572 RB_OBJ_FREEZE_RAW(x);
1574 rb_shape_transition_shape_frozen(x);
1585 RB_DEBUG_COUNTER_INC(ivar_set_base);
1590 rb_obj_ivar_set(obj,
id, val);
1595 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1596 rb_class_ivar_set(obj,
id, val);
1600 generic_ivar_set(obj,
id, val);
1609 ivar_set(obj,
id, val);
1619 ivar_set(obj,
id, val);
1628 if (rb_shape_obj_too_complex(obj)) {
1630 if (!rb_id_table_lookup(ROBJECT_IV_HASH(obj),
id, &idx)) {
1637 return RBOOL(rb_shape_get_iv_index(rb_shape_get_shape(obj),
id, &index));
1641typedef int rb_ivar_foreach_callback_func(
ID key,
VALUE val, st_data_t arg);
1642st_data_t rb_st_nth_key(
st_table *tab, st_index_t index);
1648 rb_ivar_foreach_callback_func *func;
1652iterate_over_shapes_with_callback(
rb_shape_t *shape, rb_ivar_foreach_callback_func *callback,
struct iv_itr_data * itr_data)
1654 switch ((
enum shape_type)shape->type) {
1658 iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
1662 RUBY_ASSERT(!rb_shape_obj_too_complex(itr_data->obj));
1663 iv_list = ROBJECT_IVPTR(itr_data->obj);
1667 iv_list = RCLASS_IVPTR(itr_data->obj);
1670 iv_list = itr_data->ivtbl->ivptr;
1673 VALUE val = iv_list[shape->next_iv_index - 1];
1674 if (!UNDEF_P(val)) {
1675 callback(shape->edge_name, val, itr_data->arg);
1678 case SHAPE_INITIAL_CAPACITY:
1679 case SHAPE_CAPACITY_CHANGE:
1681 case SHAPE_T_OBJECT:
1682 iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
1684 case SHAPE_OBJ_TOO_COMPLEX:
1689static enum rb_id_table_iterator_result
1690each_hash_iv(
ID id,
VALUE val,
void *data)
1693 rb_ivar_foreach_callback_func *callback = itr_data->func;
1694 return callback(
id, val, itr_data->arg);
1698obj_ivar_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1704 itr_data.func = func;
1705 if (rb_shape_obj_too_complex(obj)) {
1706 rb_id_table_foreach(ROBJECT_IV_HASH(obj), each_hash_iv, &itr_data);
1709 iterate_over_shapes_with_callback(shape, func, &itr_data);
1714gen_ivar_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1718 if (!rb_gen_ivtbl_get(obj, 0, &ivtbl))
return;
1722 itr_data.ivtbl = ivtbl;
1724 iterate_over_shapes_with_callback(shape, func, &itr_data);
1728class_ivar_each(
VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1736 iterate_over_shapes_with_callback(shape, func, &itr_data);
1751 if (rb_gen_ivtbl_get(obj, 0, &obj_ivtbl)) {
1752 if (gen_ivtbl_count(obj_ivtbl) == 0)
1755 new_ivtbl = gen_ivtbl_resize(0, obj_ivtbl->numiv);
1758 for (uint32_t i=0; i<obj_ivtbl->numiv; i++) {
1759 new_ivtbl->ivptr[i] = obj_ivtbl->ivptr[i];
1769 generic_ivtbl_no_ractor_check(clone);
1770 st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)new_ivtbl);
1774 rb_shape_t * obj_shape = rb_shape_get_shape(obj);
1775 if (rb_shape_frozen_shape_p(obj_shape)) {
1776 rb_shape_set_shape_id(clone, obj_shape->parent_id);
1779 rb_shape_set_shape(clone, obj_shape);
1792rb_replace_generic_ivar(
VALUE clone,
VALUE obj)
1798 st_data_t ivtbl, obj_data = (st_data_t)obj;
1799 if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) {
1800 st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl);
1801 st_delete(generic_iv_tbl_, &obj_data, NULL);
1818 obj_ivar_each(obj, func, arg);
1822 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
1825 class_ivar_each(obj, func, arg);
1831 gen_ivar_each(obj, func, arg);
1844 if (rb_shape_obj_too_complex(obj)) {
1845 return ROBJECT_IV_COUNT(obj);
1848 if (rb_shape_get_shape(obj)->next_iv_index > 0) {
1849 st_index_t i, count, num = ROBJECT_IV_COUNT(obj);
1850 const VALUE *
const ivptr = ROBJECT_IVPTR(obj);
1851 for (i = count = 0; i < num; ++i) {
1852 if (!UNDEF_P(ivptr[i])) {
1861 if (rb_shape_get_shape(obj)->next_iv_index > 0) {
1862 st_index_t count = 0;
1866 st_index_t i, num = rb_shape_get_shape(obj)->next_iv_index;
1867 const VALUE *
const ivptr = RCLASS_IVPTR(obj);
1868 for (i = count = 0; i < num; ++i) {
1869 if (!UNDEF_P(ivptr[i])) {
1883 if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
1884 return gen_ivtbl_count(ivtbl);
1893ivar_i(st_data_t k, st_data_t v, st_data_t a)
1899 rb_ary_push(ary,
ID2SYM(key));
1931#define rb_is_constant_id rb_is_const_id
1932#define rb_is_constant_name rb_is_const_name
1933#define id_for_var(obj, name, part, type) \
1934 id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name")
1935#define id_for_var_message(obj, name, type, message) \
1936 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
1939 int (*valid_id_p)(
ID),
int (*valid_name_p)(
VALUE),
1940 const char *message,
size_t message_len)
1943 VALUE name = *pname;
1945 if (
id ? !valid_id_p(
id) : !valid_name_p(name)) {
1946 rb_name_err_raise_str(rb_fstring_new(message, message_len),
1980 const ID id = id_for_var(obj, name, an, instance);
1990 rb_shape_t * shape = rb_shape_get_shape(obj);
1995 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1996 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
1999 if (rb_shape_obj_too_complex(obj)) {
2000 if (rb_id_table_lookup(ROBJECT_IV_HASH(obj),
id, &val)) {
2001 rb_id_table_delete(ROBJECT_IV_HASH(obj),
id);
2005 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
2010 rb_shape_transition_shape_remove_ivar(obj,
id, shape, &val);
2020 rb_name_err_raise(
"instance variable %1$s not defined",
2025NORETURN(
static void uninitialized_constant(
VALUE,
VALUE));
2027uninitialized_constant(
VALUE klass,
VALUE name)
2030 rb_name_err_raise(
"uninitialized constant %2$s::%1$s",
2033 rb_name_err_raise(
"uninitialized constant %1$s",
2040 VALUE value = rb_funcallv(klass, idConst_missing, 1, &name);
2041 rb_vm_inc_const_missing_count();
2085 VALUE ref = GET_EC()->private_const_reference;
2086 rb_vm_pop_cfunc_frame();
2088 rb_name_err_raise(
"private constant %2$s::%1$s referenced",
2091 uninitialized_constant(klass, name);
2097autoload_table_mark(
void *ptr)
2099 rb_mark_tbl_no_pin((
st_table *)ptr);
2103autoload_table_free(
void *ptr)
2109autoload_table_memsize(
const void *ptr)
2112 return st_memsize(tbl);
2116autoload_table_compact(
void *ptr)
2118 rb_gc_update_tbl_refs((
st_table *)ptr);
2123 {autoload_table_mark, autoload_table_free, autoload_table_memsize, autoload_table_compact,},
2124 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2127#define check_autoload_table(av) \
2128 (struct st_table *)rb_check_typeddata((av), &autoload_table_type)
2143 mod =
RBASIC(mod)->klass;
2151 VALUE tbl_value = rb_ivar_lookup(mod, autoload, 0);
2152 if (!tbl_value || !(tbl = check_autoload_table(tbl_value)) || !st_lookup(tbl, (st_data_t)
id, &val)) {
2165 VALUE autoload_data_value;
2177 rb_const_flag_t flag;
2193 rb_serial_t fork_gen;
2200autoload_data_compact(
void *ptr)
2204 p->feature = rb_gc_location(p->feature);
2205 p->mutex = rb_gc_location(p->mutex);
2209autoload_data_mark(
void *ptr)
2213 rb_gc_mark_movable(p->feature);
2214 rb_gc_mark_movable(p->mutex);
2218autoload_data_free(
void *ptr)
2223 if (ccan_list_empty(&p->constants)) {
2229autoload_data_memsize(
const void *ptr)
2236 {autoload_data_mark, autoload_data_free, autoload_data_memsize, autoload_data_compact},
2237 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2241autoload_const_compact(
void *ptr)
2245 ac->module = rb_gc_location(ac->module);
2246 ac->autoload_data_value = rb_gc_location(ac->autoload_data_value);
2247 ac->value = rb_gc_location(ac->value);
2248 ac->file = rb_gc_location(ac->file);
2252autoload_const_mark(
void *ptr)
2256 rb_gc_mark_movable(ac->module);
2257 rb_gc_mark_movable(ac->autoload_data_value);
2258 rb_gc_mark_movable(ac->value);
2259 rb_gc_mark_movable(ac->file);
2263autoload_const_memsize(
const void *ptr)
2269autoload_const_free(
void *ptr)
2279 {autoload_const_mark, autoload_const_free, autoload_const_memsize, autoload_const_compact,},
2280 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2284get_autoload_data(
VALUE autoload_const_value,
struct autoload_const **autoload_const_pointer)
2296 if (autoload_const_pointer) *autoload_const_pointer =
autoload_const;
2301RUBY_FUNC_EXPORTED
void
2302rb_autoload(
VALUE module,
ID name,
const char *feature)
2304 if (!feature || !*feature) {
2308 rb_autoload_str(module, name, rb_fstring_cstr(feature));
2312static void const_added(
VALUE klass,
ID const_name);
2321autoload_feature_lookup_or_create(
VALUE feature,
struct autoload_data **autoload_data_pointer)
2323 RUBY_ASSERT_MUTEX_OWNED(autoload_mutex);
2324 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2326 VALUE autoload_data_value = rb_hash_aref(autoload_features, feature);
2329 if (
NIL_P(autoload_data_value)) {
2335 if (autoload_data_pointer) *autoload_data_pointer =
autoload_data;
2337 rb_hash_aset(autoload_features, feature, autoload_data_value);
2339 else if (autoload_data_pointer) {
2340 *autoload_data_pointer =
rb_check_typeddata(autoload_data_value, &autoload_data_type);
2343 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2344 return autoload_data_value;
2348autoload_table_lookup_or_create(
VALUE module)
2350 VALUE autoload_table_value = rb_ivar_lookup(module, autoload, 0);
2351 if (autoload_table_value) {
2352 return check_autoload_table(autoload_table_value);
2356 rb_class_ivar_set(module, autoload, autoload_table_value);
2357 return (
DATA_PTR(autoload_table_value) = st_init_numtable());
2362autoload_synchronized(
VALUE _arguments)
2366 rb_const_entry_t *constant_entry = rb_const_lookup(arguments->module, arguments->name);
2367 if (constant_entry && !UNDEF_P(constant_entry->value)) {
2372 const_set(arguments->module, arguments->name,
Qundef);
2374 struct st_table *autoload_table = autoload_table_lookup_or_create(arguments->module);
2377 VALUE feature = rb_fstring(arguments->feature);
2380 VALUE autoload_data_value = autoload_feature_lookup_or_create(feature, &
autoload_data);
2391 st_insert(autoload_table, (st_data_t)arguments->name, (st_data_t)autoload_const_value);
2405 if (!RSTRING_LEN(feature)) {
2417 if (result ==
Qtrue) {
2418 const_added(module, name);
2423autoload_delete(
VALUE module,
ID name)
2425 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2427 st_data_t load = 0, key = name;
2431 VALUE table_value = rb_ivar_lookup(module, autoload, 0);
2433 struct st_table *table = check_autoload_table(table_value);
2435 st_delete(table, &key, &load);
2457 if (table->num_entries == 0) {
2458 rb_attr_delete(module, autoload);
2463 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2469 return ele->mutex !=
Qnil && !rb_mutex_owned_p(ele->mutex);
2473check_autoload_required(
VALUE mod,
ID id,
const char **loadingpath)
2477 const char *loading;
2479 if (!autoload_const_value || !(
autoload_data = get_autoload_data(autoload_const_value, 0))) {
2492 return autoload_const_value;
2495 loading = RSTRING_PTR(feature);
2498 return autoload_const_value;
2501 if (loadingpath && loading) {
2502 *loadingpath = loading;
2503 return autoload_const_value;
2511MJIT_FUNC_EXPORTED
int
2512rb_autoloading_value(
VALUE mod,
ID id,
VALUE* value, rb_const_flag_t *flag)
2515 if (!ac)
return FALSE;
2531 return ele->mutex !=
Qnil && rb_mutex_owned_p(ele->mutex);
2538autoloading_const_entry(
VALUE mod,
ID id)
2545 if (!load || !(ele = get_autoload_data(load, &ac))) {
2551 if (autoload_by_current(ele)) {
2552 if (!UNDEF_P(ac->value)) {
2561autoload_defined_p(
VALUE mod,
ID id)
2566 if (!ce || !UNDEF_P(ce->value)) {
2572 return !rb_autoloading_value(mod,
id, NULL, NULL);
2594 check_before_mod_set(ac->module, ac->name, ac->value,
"constant");
2598 const_tbl_update(ac,
true);
2606autoload_load_needed(
VALUE _arguments)
2610 const char *loading = 0, *src;
2612 if (!autoload_defined_p(arguments->module, arguments->name)) {
2616 VALUE autoload_const_value = check_autoload_required(arguments->module, arguments->name, &loading);
2617 if (!autoload_const_value) {
2622 if (src && loading && strcmp(src, loading) == 0) {
2643 return autoload_const_value;
2647autoload_apply_constants(
VALUE _arguments)
2649 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2661 ccan_list_for_each_safe(&arguments->autoload_data->constants,
autoload_const, next, cnode) {
2667 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2673autoload_feature_require(
VALUE _arguments)
2682 VALUE result = rb_funcall(rb_vm_top_self(), rb_intern(
"require"), 1, arguments->autoload_data->feature);
2684 if (
RTEST(result)) {
2692autoload_try_load(
VALUE _arguments)
2696 VALUE result = autoload_feature_require(_arguments);
2699 rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name);
2701 if (!ce || UNDEF_P(ce->value)) {
2706 if (arguments->module == rb_cObject) {
2708 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
" but it didn't",
2709 arguments->autoload_data->feature,
2715 "Expected %"PRIsVALUE
" to define %"PRIsVALUE
"::%"PRIsVALUE
" but it didn't",
2716 arguments->autoload_data->feature,
2724 ce->flag |= arguments->flag;
2736 if (!ce || !UNDEF_P(ce->value)) {
2741 if (UNLIKELY(!rb_ractor_main_p())) {
2742 rb_raise(rb_eRactorUnsafeError,
"require by autoload on non-main Ractor is not supported (%s)",
rb_id2name(name));
2752 if (autoload_const_value ==
Qfalse)
return autoload_const_value;
2754 arguments.flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2771 return rb_autoload_at_p(mod,
id, TRUE);
2775rb_autoload_at_p(
VALUE mod,
ID id,
int recur)
2780 while (!autoload_defined_p(mod,
id)) {
2781 if (!recur)
return Qnil;
2783 if (!mod)
return Qnil;
2785 load = check_autoload_required(mod,
id, 0);
2786 if (!load)
return Qnil;
2787 return (ele = get_autoload_data(load, 0)) ? ele->feature :
Qnil;
2790MJIT_FUNC_EXPORTED
void
2793 if (RB_CONST_DEPRECATED_P(ce) &&
2795 if (klass == rb_cObject) {
2806rb_const_get_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
2808 VALUE c = rb_const_search(klass,
id, exclude, recurse, visibility);
2810 if (UNLIKELY(!rb_ractor_main_p())) {
2812 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));
2817 return rb_const_missing(klass,
ID2SYM(
id));
2821rb_const_search_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
2823 VALUE value, current;
2824 bool first_iteration =
true;
2826 for (current = klass;
2828 current =
RCLASS_SUPER(current), first_iteration =
false) {
2833 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
2846 while ((ce = rb_const_lookup(tmp,
id))) {
2847 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2848 GET_EC()->private_const_reference = tmp;
2851 rb_const_warn_if_deprecated(ce, tmp,
id);
2853 if (UNDEF_P(value)) {
2855 if (am == tmp)
break;
2857 ac = autoloading_const_entry(tmp,
id);
2858 if (ac)
return ac->value;
2862 if (exclude && tmp == rb_cObject) {
2867 if (!recurse)
break;
2871 GET_EC()->private_const_reference = 0;
2876rb_const_search(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
2880 if (klass == rb_cObject) exclude = FALSE;
2881 value = rb_const_search_from(klass,
id, exclude, recurse, visibility);
2882 if (!UNDEF_P(value))
return value;
2883 if (exclude)
return value;
2886 return rb_const_search_from(rb_cObject,
id, FALSE, recurse, visibility);
2892 return rb_const_get_0(klass,
id, TRUE, TRUE, FALSE);
2898 return rb_const_get_0(klass,
id, FALSE, TRUE, FALSE);
2904 return rb_const_get_0(klass,
id, TRUE, FALSE, FALSE);
2907MJIT_FUNC_EXPORTED
VALUE
2908rb_public_const_get_from(
VALUE klass,
ID id)
2910 return rb_const_get_0(klass,
id, TRUE, TRUE, TRUE);
2913MJIT_FUNC_EXPORTED
VALUE
2914rb_public_const_get_at(
VALUE klass,
ID id)
2916 return rb_const_get_0(klass,
id, TRUE, FALSE, TRUE);
2919NORETURN(
static void undefined_constant(
VALUE mod,
VALUE name));
2923 rb_name_err_raise(
"constant %2$s::%1$s not defined",
2928rb_const_location_from(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
2930 while (
RTEST(klass)) {
2933 while ((ce = rb_const_lookup(klass,
id))) {
2934 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2937 if (exclude && klass == rb_cObject) {
2940 if (
NIL_P(ce->file))
return rb_ary_new();
2941 return rb_assoc_new(ce->file,
INT2NUM(ce->line));
2943 if (!recurse)
break;
2952rb_const_location(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
2956 if (klass == rb_cObject) exclude = FALSE;
2957 loc = rb_const_location_from(klass,
id, exclude, recurse, visibility);
2958 if (!
NIL_P(loc))
return loc;
2959 if (exclude)
return loc;
2962 return rb_const_location_from(rb_cObject,
id, FALSE, recurse, visibility);
2966rb_const_source_location(
VALUE klass,
ID id)
2968 return rb_const_location(klass,
id, FALSE, TRUE, FALSE);
2971MJIT_FUNC_EXPORTED
VALUE
2972rb_const_source_location_at(
VALUE klass,
ID id)
2974 return rb_const_location(klass,
id, TRUE, FALSE, FALSE);
2990 const ID id = id_for_var(mod, name, a, constant);
2993 undefined_constant(mod, name);
3006 ce = rb_const_lookup(mod,
id);
3007 if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod),
id)) {
3009 rb_name_err_raise(
"cannot remove %2$s::%1$s", mod,
ID2SYM(
id));
3012 undefined_constant(mod,
ID2SYM(
id));
3020 autoload_delete(mod,
id);
3030cv_i_update(st_data_t *k, st_data_t *v, st_data_t a,
int existing)
3032 if (existing)
return ST_STOP;
3037static enum rb_id_table_iterator_result
3044 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
3046 return ID_TABLE_CONTINUE;
3049static enum rb_id_table_iterator_result
3050rb_local_constants_i(
ID const_name,
VALUE const_value,
void *ary)
3055 return ID_TABLE_CONTINUE;
3059rb_local_constants(
VALUE mod)
3069 rb_id_table_foreach(tbl, rb_local_constants_i, (
void *)ary);
3081 tbl = st_init_numtable();
3083 if (RCLASS_CONST_TBL(mod)) {
3086 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
3101 if (tmp == rb_cObject && mod != rb_cObject)
break;
3107list_i(st_data_t key, st_data_t value,
VALUE ary)
3111 if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary,
ID2SYM(sym));
3150 bool inherit =
true;
3152 if (rb_check_arity(argc, 0, 1)) inherit =
RTEST(argv[0]);
3158 return rb_local_constants(mod);
3163rb_const_defined_0(
VALUE klass,
ID id,
int exclude,
int recurse,
int visibility)
3172 if ((ce = rb_const_lookup(tmp,
id))) {
3173 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3176 if (UNDEF_P(ce->value) && !check_autoload_required(tmp,
id, 0) &&
3177 !rb_autoloading_value(tmp,
id, NULL, NULL))
3180 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3186 if (!recurse)
break;
3200 return rb_const_defined_0(klass,
id, TRUE, TRUE, FALSE);
3206 return rb_const_defined_0(klass,
id, FALSE, TRUE, FALSE);
3212 return rb_const_defined_0(klass,
id, TRUE, FALSE, FALSE);
3215MJIT_FUNC_EXPORTED
int
3216rb_public_const_defined_from(
VALUE klass,
ID id)
3218 return rb_const_defined_0(klass,
id, TRUE, TRUE, TRUE);
3222check_before_mod_set(
VALUE klass,
ID id,
VALUE val,
const char *dest)
3227static void set_namespace_path(
VALUE named_namespace,
VALUE name);
3229static enum rb_id_table_iterator_result
3230set_namespace_path_i(
ID id,
VALUE v,
void *payload)
3233 VALUE value = ce->value;
3234 int has_permanent_classpath;
3237 return ID_TABLE_CONTINUE;
3239 classname(value, &has_permanent_classpath);
3240 if (has_permanent_classpath) {
3241 return ID_TABLE_CONTINUE;
3243 set_namespace_path(value, build_const_path(parental_path,
id));
3244 rb_attr_delete(value, tmp_classpath);
3246 return ID_TABLE_CONTINUE;
3255set_namespace_path(
VALUE named_namespace,
VALUE namespace_path)
3257 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3261 rb_class_ivar_set(named_namespace, classpath, namespace_path);
3263 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3270const_added(
VALUE klass,
ID const_name)
3272 if (GET_VM()->running) {
3274 rb_funcallv(klass, idConst_added, 1, &name);
3289 rb_raise(rb_eRactorIsolationError,
"can not set constants with non-shareable objects by non-main Ractors");
3292 check_before_mod_set(klass,
id, val,
"constant");
3296 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3298 RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
3301 rb_id_table_insert(tbl,
id, (
VALUE)ce);
3302 setup_const_entry(ce, klass, val, CONST_PUBLIC);
3306 .module = klass, .name = id,
3307 .value = val, .flag = CONST_PUBLIC,
3310 ac.file = rb_source_location(&ac.line);
3311 const_tbl_update(&ac,
false);
3320 if (rb_cObject && rb_namespace_p(val)) {
3321 int val_path_permanent;
3322 VALUE val_path = classname(val, &val_path_permanent);
3323 if (
NIL_P(val_path) || !val_path_permanent) {
3324 if (klass == rb_cObject) {
3325 set_namespace_path(val, rb_id2str(
id));
3328 int parental_path_permanent;
3329 VALUE parental_path = classname(klass, &parental_path_permanent);
3330 if (
NIL_P(parental_path)) {
3332 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
3334 if (parental_path_permanent && !val_path_permanent) {
3335 set_namespace_path(val, build_const_path(parental_path,
id));
3337 else if (!parental_path_permanent &&
NIL_P(val_path)) {
3338 ivar_set(val, tmp_classpath, build_const_path(parental_path,
id));
3348 const_set(klass,
id, val);
3349 const_added(klass,
id);
3353autoload_data_for_named_constant(
VALUE module,
ID name,
struct autoload_const **autoload_const_pointer)
3356 if (!autoload_data_value)
return 0;
3373 VALUE klass = ac->module;
3374 VALUE val = ac->value;
3376 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3377 rb_const_flag_t visibility = ac->flag;
3380 if (rb_id_table_lookup(tbl,
id, &value)) {
3382 if (UNDEF_P(ce->value)) {
3383 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3384 VALUE file = ac->file;
3385 int line = ac->line;
3386 struct autoload_data *ele = autoload_data_for_named_constant(klass,
id, &ac);
3388 if (!autoload_force && ele) {
3392 ac->file = rb_source_location(&ac->line);
3396 autoload_delete(klass,
id);
3397 ce->flag = visibility;
3402 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3406 VALUE name = QUOTE_ID(
id);
3407 visibility = ce->flag;
3408 if (klass == rb_cObject)
3409 rb_warn(
"already initialized constant %"PRIsVALUE
"", name);
3411 rb_warn(
"already initialized constant %"PRIsVALUE
"::%"PRIsVALUE
"",
3413 if (!
NIL_P(ce->file) && ce->line) {
3415 "previous definition of %"PRIsVALUE
" was here", name);
3419 setup_const_entry(ce, klass, val, visibility);
3425 rb_id_table_insert(tbl,
id, (
VALUE)ce);
3426 setup_const_entry(ce, klass, val, visibility);
3432 rb_const_flag_t visibility)
3434 ce->flag = visibility;
3436 RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
3442 ID id = rb_intern(name);
3445 rb_warn(
"rb_define_const: invalid name `%s' for constant", name);
3447 rb_gc_register_mark_object(val);
3458set_const_visibility(
VALUE mod,
int argc,
const VALUE *argv,
3459 rb_const_flag_t flag, rb_const_flag_t mask)
3467 rb_warning(
"%"PRIsVALUE
" with no argument is just ignored",
3468 QUOTE_ID(rb_frame_callee()));
3472 for (i = 0; i < argc; i++) {
3474 VALUE val = argv[i];
3477 undefined_constant(mod, val);
3479 if ((ce = rb_const_lookup(mod,
id))) {
3482 if (UNDEF_P(ce->value)) {
3485 ele = autoload_data_for_named_constant(mod,
id, &ac);
3494 undefined_constant(mod,
ID2SYM(
id));
3504 long len = strlen(name);
3508 undefined_constant(mod, rb_fstring_new(name, len));
3510 if (!(ce = rb_const_lookup(mod,
id))) {
3511 undefined_constant(mod,
ID2SYM(
id));
3513 ce->flag |= CONST_DEPRECATED;
3524rb_mod_private_constant(
int argc,
const VALUE *argv,
VALUE obj)
3526 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
3538rb_mod_public_constant(
int argc,
const VALUE *argv,
VALUE obj)
3540 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
3564rb_mod_deprecate_constant(
int argc,
const VALUE *argv,
VALUE obj)
3566 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3571original_module(
VALUE c)
3579cvar_lookup_at(
VALUE klass,
ID id, st_data_t *v)
3587 klass =
RBASIC(klass)->klass;
3592 if (UNDEF_P(n))
return 0;
3599cvar_front_klass(
VALUE klass)
3603 if (rb_namespace_p(obj)) {
3613 if (front && target != front) {
3614 if (original_module(front) != original_module(target)) {
3616 "class variable % "PRIsVALUE
" of %"PRIsVALUE
" is overtaken by %"PRIsVALUE
"",
3621 rb_ivar_delete(front,
id,
Qundef);
3630 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR();
3631 if (cvar_lookup_at(klass,
id, (&v))) {
3638 for (klass = cvar_front_klass(klass); klass; klass =
RCLASS_SUPER(klass)) {
3639 if (cvar_lookup_at(klass,
id, (&v))) {
3650#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3651 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3652 if (cvar_lookup_at(klass, id, (v))) { \
3657#define CVAR_LOOKUP(v,r) do {\
3658 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
3659 if (cvar_lookup_at(klass, id, (v))) {r;}\
3660 CVAR_FOREACH_ANCESTORS(klass, v, r);\
3664check_for_cvar_table(
VALUE subclass,
VALUE key)
3668 RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
3669 ruby_vm_global_cvar_state++;
3673 rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
3679 VALUE tmp, front = 0, target = 0;
3682 CVAR_LOOKUP(0, {
if (!front) front = klass; target = klass;});
3684 cvar_overtaken(front, target,
id);
3691 target =
RBASIC(target)->klass;
3693 check_before_mod_set(target,
id, val,
"class variable");
3695 int result = rb_class_ivar_set(target,
id, val);
3697 struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
3700 rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
3706 if (!rb_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
3708 ent->class_value = target;
3709 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3710 rb_id_table_insert(rb_cvc_tbl,
id, (
VALUE)ent);
3711 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
3714 ent = (
void *)ent_data;
3715 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3722 if (RB_TYPE_P(target,
T_CLASS)) {
3723 if (RCLASS_SUBCLASSES(target)) {
3724 rb_class_foreach_subclass(target, check_for_cvar_table,
id);
3736 value = find_cvar(klass, front, &target,
id);
3738 rb_name_err_raise(
"uninitialized class variable %1$s in %2$s",
3741 cvar_overtaken(*front, target,
id);
3742 return (
VALUE)value;
3755 if (!klass)
return Qfalse;
3756 CVAR_LOOKUP(0,
return Qtrue);
3761cv_intern(
VALUE klass,
const char *name)
3763 ID id = rb_intern(name);
3765 rb_name_err_raise(
"wrong class variable name %1$s",
3774 ID id = cv_intern(klass, name);
3781 ID id = cv_intern(klass, name);
3792cv_i(st_data_t k, st_data_t v, st_data_t a)
3798 st_update(tbl, (st_data_t)key, cv_i_update, 0);
3804mod_cvar_at(
VALUE mod,
void *data)
3808 tbl = st_init_numtable();
3810 mod = original_module(mod);
3817mod_cvar_of(
VALUE mod,
void *data)
3821 if (rb_namespace_p(
rb_ivar_get(mod, id__attached__))) {
3822 data = mod_cvar_at(tmp, data);
3823 tmp = cvar_front_klass(tmp);
3827 data = mod_cvar_at(tmp, data);
3835cv_list_i(st_data_t key, st_data_t value,
VALUE ary)
3838 rb_ary_push(ary,
ID2SYM(sym));
3843cvar_list(
void *data)
3879 bool inherit =
true;
3882 if (rb_check_arity(argc, 0, 1)) inherit =
RTEST(argv[0]);
3884 tbl = mod_cvar_of(mod, 0);
3887 tbl = mod_cvar_at(mod, 0);
3889 return cvar_list(tbl);
3914 const ID id = id_for_var_message(mod, name,
class,
"wrong class variable name %1$s");
3921 val = rb_ivar_delete(mod,
id,
Qundef);
3922 if (!UNDEF_P(val)) {
3926 rb_name_err_raise(
"cannot remove %1$s for %2$s", mod,
ID2SYM(
id));
3929 rb_name_err_raise(
"class variable %1$s not defined for %2$s",
3948 ID id = rb_intern(name);
3962 rb_shape_t * shape = rb_shape_get_shape(obj);
3964 found = rb_shape_get_iv_index(shape, key, &idx);
3970 RCLASS_IVPTR(obj)[idx] = value;
3977 idx = shape->next_iv_index;
3978 shape = rb_shape_get_next(shape, obj, key);
3982 if ((idx & (idx - 1)) == 0) {
3983 size_t newsize = idx ? idx * 2 : 1;
3990 rb_shape_set_shape(obj, shape);
3999tbl_copy_i(st_data_t key, st_data_t val, st_data_t dest)
4001 rb_class_ivar_set(dest, key, val);
4012 RUBY_ASSERT(RCLASS_SHAPE_ID(dst) == ROOT_SHAPE_ID || rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(dst))->
type == SHAPE_INITIAL_CAPACITY);
4019rb_const_lookup(
VALUE klass,
ID id)
4021 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4028 r = rb_id_table_lookup(tbl,
id, &val);
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_EXTERN
Declaration of externally visible global variables.
void rb_obj_freeze_inline(VALUE obj)
Prevents further modifications to the given object.
@ RUBY_FL_SINGLETON
This flag has something to do with an object's class.
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().
#define rb_str_new2
Old name of rb_str_new_cstr.
#define FL_SINGLETON
Old name of RUBY_FL_SINGLETON.
#define FL_EXIVAR
Old name of RUBY_FL_EXIVAR.
#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 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 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 always regardless of runtime -W flag.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_compile_warn(const char *file, int line, const char *fmt,...)
Identical to rb_compile_warning(), except it reports always regardless of runtime -W flag.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
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 always regardless of runtime -W flag.
VALUE rb_eArgError
ArgumentError exception.
void rb_warning(const char *fmt,...)
Issues a warning.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_cObject
Documented in include/ruby/internal/globals.h.
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.
#define rb_check_frozen
Just another name of rb_check_frozen.
#define rb_check_frozen_internal(obj)
#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_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_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.
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
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.
ID rb_intern2(const char *name, long len)
Identical to rb_intern(), except it additionally takes the length of the string.
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(), except it takes an instance of rb_cString.
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
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.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
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
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
#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 RBASIC(obj)
Convenient casting macro.
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
#define DATA_PTR(obj)
Convenient getter macro.
#define ROBJECT(obj)
Convenient casting 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.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
uintptr_t VALUE
Type that represents a Ruby object.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.