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"
39#include "ractor_core.h"
43#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
45typedef void rb_gvar_compact_t(
void *var);
48static ID autoload, classpath, tmp_classpath;
49static VALUE autoload_featuremap;
51static void check_before_mod_set(VALUE, ID, VALUE,
const char *);
52static void setup_const_entry(
rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
53static VALUE rb_const_search(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility);
68 rb_global_tbl = rb_id_table_create(0);
69 generic_iv_tbl_ = st_init_numtable();
78rb_namespace_p(VALUE obj)
97classname(VALUE klass,
int *permanent)
103 if (!RCLASS_EXT(klass))
return Qnil;
104 if (!(ivtbl = RCLASS_IV_TBL(klass)))
return Qnil;
105 if (st_lookup(ivtbl, (st_data_t)classpath, &n)) {
109 if (st_lookup(ivtbl, (st_data_t)tmp_classpath, &n))
return (VALUE)n;
124 return classname(mod, &permanent);
128make_temporary_path(VALUE obj, VALUE klass)
136 path =
rb_sprintf(
"#<Module:%p>", (
void*)obj);
139 path =
rb_sprintf(
"#<%"PRIsVALUE
":%p>", klass, (
void*)obj);
146typedef VALUE (*fallback_func)(VALUE obj, VALUE name);
149rb_tmp_class_path(VALUE klass,
int *permanent, fallback_func fallback)
151 VALUE path = classname(klass, permanent);
158 if (rb_obj_class(klass) == rb_cModule) {
163 path = rb_tmp_class_path(
RBASIC(klass)->klass, &perm, fallback);
167 return fallback(klass, path);
175 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
187no_fallback(VALUE obj, VALUE name)
193rb_search_class_path(VALUE klass)
196 return rb_tmp_class_path(klass, &permanent, no_fallback);
200build_const_pathname(VALUE head, VALUE tail)
205 return rb_fstring(path);
209build_const_path(VALUE head, ID tail)
211 return build_const_pathname(head,
rb_id2str(tail));
218 ID pathid = classpath;
220 if (under == rb_cObject) {
225 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
226 str = build_const_pathname(str, name);
228 pathid = tmp_classpath;
246 const char *pbeg, *pend, *p, *path =
RSTRING_PTR(pathname);
248 VALUE c = rb_cObject;
251 rb_raise(rb_eArgError,
"invalid class path encoding (non ASCII)");
255 if (path == pend || path[0] ==
'#') {
256 rb_raise(rb_eArgError,
"can't retrieve anonymous class %"PRIsVALUE,
260 while (p < pend && *p !=
':') p++;
262 if (p < pend && p[0] ==
':') {
263 if ((
size_t)(pend - p) < 2 || p[1] !=
':')
goto undefined_class;
268 goto undefined_class;
270 c = rb_const_search(c,
id, TRUE, FALSE, FALSE);
271 if (c ==
Qundef)
goto undefined_class;
272 if (!rb_namespace_p(c)) {
273 rb_raise(rb_eTypeError,
"%"PRIsVALUE
" does not refer to class/module",
282 rb_raise(rb_eArgError,
"undefined class/module % "PRIsVALUE,
303 VALUE path = rb_tmp_class_path(
rb_class_real(klass), &permanent, make_temporary_path);
304 if (
NIL_P(path))
return NULL;
316 void (*func)(VALUE arg, VALUE val);
328 rb_gvar_compact_t *compactor;
339rb_find_global_entry(ID
id)
344 if (!rb_id_table_lookup(rb_global_tbl,
id, &data)) {
352 if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
353 rb_raise(rb_eRactorIsolationError,
"can not access global variables %s from non-main Ractors",
rb_id2name(
id));
360rb_gvar_ractor_local(
const char *name)
363 entry->ractor_local =
true;
367rb_gvar_undef_compactor(
void *var)
381 entry->ractor_local =
false;
387 var->compactor = rb_gvar_undef_compactor;
389 var->block_trace = 0;
391 rb_id_table_insert(rb_global_tbl,
id, (VALUE)entry);
399 rb_warning(
"global variable `%"PRIsVALUE
"' not initialized", QUOTE_ID(
id));
405rb_gvar_val_compactor(
void *_var)
409 VALUE obj = (
VALUE)var->data;
414 var->data = (
void*)
new;
426 var->compactor = rb_gvar_val_compactor;
428 var->data = (
void*)val;
446 var->data = (
void*)val;
452 VALUE data = (
VALUE)var;
459 if (!var)
return Qnil;
478 rb_name_error(
id,
"%"PRIsVALUE
" is a read-only variable", QUOTE_ID(
id));
481static enum rb_id_table_iterator_result
482mark_global_entry(VALUE v,
void *ignored)
488 (*var->marker)(var->data);
494 return ID_TABLE_CONTINUE;
498rb_gc_mark_global_tbl(
void)
501 rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
505static enum rb_id_table_iterator_result
506update_global_entry(VALUE v,
void *ignored)
511 (*var->compactor)(var);
512 return ID_TABLE_CONTINUE;
516rb_gc_update_global_tbl(
void)
519 rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
524global_id(
const char *name)
528 if (name[0] ==
'$')
id =
rb_intern(name);
530 size_t len = strlen(name);
532 char *buf =
ALLOCV_N(
char, vbuf, len+1);
534 memcpy(buf+1, name, len);
542find_global_id(
const char *name)
545 size_t len = strlen(name);
547 if (name[0] ==
'$') {
552 char *buf =
ALLOCV_N(
char, vbuf, len+1);
554 memcpy(buf+1, name, len);
569 volatile VALUE tmp = var ? *var :
Qnil;
570 ID
id = global_id(name);
573 gvar->data = (
void*)var;
605rb_trace_eval(VALUE cmd, VALUE val)
625 trace->next = entry->var->trace;
626 trace->func = rb_trace_eval;
629 entry->var->trace = trace;
643 while (trace->next) {
646 trace->next = next->next;
667 rb_name_error_str(var,
"undefined global variable %"PRIsVALUE
"", QUOTE(var));
669 if ((entry = rb_find_global_entry(
id)) == NULL) {
670 rb_name_error(
id,
"undefined global variable %"PRIsVALUE
"", QUOTE_ID(
id));
673 trace = entry->var->trace;
684 if (!entry->var->block_trace) remove_trace(entry->var);
689 if (trace->data == cmd) {
691 if (!entry->var->block_trace) remove_trace(entry->var);
712 (*trace->func)(trace->data, data->val);
723 var->block_trace = 0;
734 (*var->setter)(val, entry->id, var->data);
736 if (var->trace && !var->block_trace) {
737 var->block_trace = 1;
738 trace.trace = var->trace;
740 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
746rb_gvar_set(ID
id, VALUE val)
751 return rb_gvar_set_entry(entry, val);
757 return rb_gvar_set(global_id(name), val);
765 return (*var->getter)(entry->id, var->data);
771 ID
id = find_global_id(name);
774 rb_warning(
"global variable `%s' not initialized", name);
778 return rb_gvar_get(
id);
781MJIT_FUNC_EXPORTED VALUE
782rb_gvar_defined(ID
id)
789rb_gvar_getter_function_of(ID
id)
792 return entry->var->getter;
796rb_gvar_setter_function_of(ID
id)
799 return entry->var->setter;
802static enum rb_id_table_iterator_result
803gvar_i(ID key, VALUE val,
void *a)
805 VALUE ary = (
VALUE)a;
807 return ID_TABLE_CONTINUE;
816 if (!rb_ractor_main_p()) {
817 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
820 rb_id_table_foreach(rb_global_tbl, gvar_i, (
void *)ary);
821 if (!
NIL_P(backref)) {
823 int i, nmatch = rb_match_count(backref);
825 for (i = 1; i <= nmatch; ++i) {
826 if (!rb_match_nth_defined(i, backref))
continue;
829 buf[1] = (char)(i +
'0');
849 if (!rb_ractor_main_p()) {
850 rb_raise(rb_eRactorIsolationError,
"can not access global variables from non-main Ractors");
854 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
857 rb_id_table_insert(gtbl, name1, (VALUE)entry1);
859 else if ((entry1 = (
struct rb_global_entry *)data1)->var != entry2->var) {
861 if (var->block_trace) {
862 rb_raise(rb_eRuntimeError,
"can't alias in tracer");
865 if (var->counter == 0) {
878 entry2->var->counter++;
879 entry1->var = entry2->var;
883iv_index_tbl_lookup(
struct st_table *tbl, ID
id, uint32_t *indexp)
888 if (tbl == NULL)
return false;
892 r = st_lookup(tbl, (st_data_t)
id, &ent_data);
898 *indexp = ent->index;
907IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID
id)
909 if (UNLIKELY(!rb_ractor_main_p())) {
911 rb_raise(rb_eRactorIsolationError,
"can not set instance variables of classes/modules by non-main Ractors");
916#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
917 if (UNLIKELY(!rb_ractor_main_p())) { \
918 rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
922generic_ivtbl(VALUE obj, ID
id,
bool force_check_ractor)
928 UNLIKELY(!rb_ractor_main_p()) &&
931 rb_raise(rb_eRactorIsolationError,
"can not access instance variables of shareable objects from non-main Ractors");
933 return generic_iv_tbl_;
937generic_ivtbl_no_ractor_check(VALUE obj)
939 return generic_ivtbl(obj, 0,
false);
943gen_ivtbl_get(VALUE obj, ID
id,
struct gen_ivtbl **ivtbl)
950 if (st_lookup(generic_ivtbl(obj,
id,
false), (st_data_t)obj, &data)) {
960MJIT_FUNC_EXPORTED
int
961rb_ivar_generic_ivtbl_lookup(VALUE obj,
struct gen_ivtbl **ivtbl)
963 return gen_ivtbl_get(obj, 0, ivtbl);
966MJIT_FUNC_EXPORTED VALUE
967rb_ivar_generic_lookup_with_index(VALUE obj, ID
id, uint32_t index)
971 if (gen_ivtbl_get(obj,
id, &ivtbl)) {
972 if (LIKELY(index < ivtbl->numiv)) {
973 VALUE val = ivtbl->ivptr[index];
982generic_ivar_delete(VALUE obj, ID
id, VALUE undef)
986 if (gen_ivtbl_get(obj,
id, &ivtbl)) {
987 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
990 if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl,
id, &index)) {
991 if (index < ivtbl->numiv) {
992 VALUE ret = ivtbl->ivptr[index];
994 ivtbl->ivptr[index] =
Qundef;
995 return ret ==
Qundef ? undef : ret;
1003generic_ivar_get(VALUE obj, ID
id, VALUE undef)
1007 if (gen_ivtbl_get(obj,
id, &ivtbl)) {
1008 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1011 if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl,
id, &index)) {
1012 if (index < ivtbl->numiv) {
1013 VALUE ret = ivtbl->ivptr[index];
1015 return ret ==
Qundef ? undef : ret;
1023gen_ivtbl_bytes(
size_t n)
1029gen_ivtbl_resize(
struct gen_ivtbl *old, uint32_t n)
1031 uint32_t len = old ? old->numiv : 0;
1035 for (; len < n; len++) {
1036 ivtbl->ivptr[len] =
Qundef;
1044gen_ivtbl_dup(
const struct gen_ivtbl *orig)
1046 size_t s = gen_ivtbl_bytes(orig->numiv);
1049 memcpy(ivtbl, orig, s);
1058 if (!ivup->iv_extended) {
1059 return (uint32_t)ivup->u.iv_index_tbl->num_entries;
1062 uint32_t index = (uint32_t)ivup->index;
1063 return (index+1) + (index+1)/4;
1068generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u,
int existing)
1070 ASSERT_vm_locking();
1077 if (ivup->index < ivtbl->numiv) {
1078 ivup->u.ivtbl = ivtbl;
1083 uint32_t newsize = iv_index_tbl_newsize(ivup);
1084 ivtbl = gen_ivtbl_resize(ivtbl, newsize);
1085 *v = (st_data_t)ivtbl;
1086 ivup->u.ivtbl = ivtbl;
1091generic_ivar_defined(VALUE obj, ID
id)
1094 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1097 if (!iv_index_tbl_lookup(iv_index_tbl,
id, &index))
return Qfalse;
1098 if (!gen_ivtbl_get(obj,
id, &ivtbl))
return Qfalse;
1100 return RBOOL((index < ivtbl->numiv) && (ivtbl->ivptr[index] !=
Qundef));
1104generic_ivar_remove(VALUE obj, ID
id, VALUE *valp)
1108 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1110 if (!iv_index_tbl)
return 0;
1111 if (!iv_index_tbl_lookup(iv_index_tbl,
id, &index))
return 0;
1112 if (!gen_ivtbl_get(obj,
id, &ivtbl))
return 0;
1114 if (index < ivtbl->numiv) {
1115 if (ivtbl->ivptr[index] !=
Qundef) {
1116 *valp = ivtbl->ivptr[index];
1117 ivtbl->ivptr[index] =
Qundef;
1125gen_ivtbl_mark(
const struct gen_ivtbl *ivtbl)
1129 for (i = 0; i < ivtbl->numiv; i++) {
1135rb_mark_generic_ivar(VALUE obj)
1139 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1140 gen_ivtbl_mark(ivtbl);
1145rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
1147 st_data_t key = (st_data_t)rsrc;
1150 if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl))
1151 st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl);
1157 st_data_t key = (st_data_t)obj, ivtbl;
1159 if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, &ivtbl))
1163RUBY_FUNC_EXPORTED
size_t
1164rb_generic_ivar_memsize(VALUE obj)
1168 if (gen_ivtbl_get(obj, 0, &ivtbl))
1169 return gen_ivtbl_bytes(ivtbl->numiv);
1174gen_ivtbl_count(
const struct gen_ivtbl *ivtbl)
1179 for (i = 0; i < ivtbl->numiv; i++) {
1180 if (ivtbl->ivptr[i] !=
Qundef) {
1189lock_st_lookup(
st_table *tab, st_data_t key, st_data_t *value)
1194 r = st_lookup(tab, key, value);
1201lock_st_delete(
st_table *tab, st_data_t *key, st_data_t *value)
1206 r = st_delete(tab, key, value);
1213lock_st_is_member(
st_table *tab, st_data_t key)
1218 r = st_is_member(tab, key);
1225lock_st_insert(
st_table *tab, st_data_t key, st_data_t value)
1230 r = st_insert(tab, key, value);
1237rb_ivar_lookup(VALUE obj, ID
id, VALUE undef)
1248 if (iv_index_tbl_lookup(ROBJECT_IV_INDEX_TBL(obj),
id, &index) &&
1250 (val = ptr[index]) !=
Qundef) {
1262 if (RCLASS_IV_TBL(obj) &&
1263 lock_st_lookup(RCLASS_IV_TBL(obj), (st_data_t)
id, &val)) {
1265 UNLIKELY(!rb_ractor_main_p()) &&
1268 "can not get unshareable values from instance variables of classes/modules from non-main Ractors");
1278 return generic_ivar_get(obj,
id, undef);
1287 VALUE iv = rb_ivar_lookup(obj,
id,
Qnil);
1288 RB_DEBUG_COUNTER_INC(ivar_get_base);
1295 return rb_ivar_lookup(obj,
id,
Qnil);
1299rb_ivar_delete(VALUE obj, ID
id, VALUE undef)
1303 uint32_t len, index;
1310 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1311 if (iv_index_tbl_lookup(iv_index_tbl,
id, &index) &&
1313 VALUE val = ptr[index];
1323 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1324 if (RCLASS_IV_TBL(obj)) {
1325 st_data_t id_data = (st_data_t)
id, val;
1326 if (lock_st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) {
1333 return generic_ivar_delete(obj,
id, undef);
1340rb_attr_delete(VALUE obj, ID
id)
1342 return rb_ivar_delete(obj,
id,
Qnil);
1346iv_index_tbl_make(VALUE obj, VALUE klass)
1350 if (UNLIKELY(!klass)) {
1351 rb_raise(rb_eTypeError,
"hidden object cannot have instance variables");
1354 if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
1356 if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
1357 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
1362 return iv_index_tbl;
1366iv_index_tbl_extend(
struct ivar_update *ivup, ID
id, VALUE klass)
1368 ASSERT_vm_locking();
1372 if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)
id, &ent_data)) {
1373 ent = (
void *)ent_data;
1374 ivup->index = ent->index;
1377 if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) {
1378 rb_raise(rb_eArgError,
"too many instance variables");
1381 ent->index = ivup->index = (uint32_t)ivup->u.iv_index_tbl->num_entries;
1382 ent->class_value = klass;
1383 ent->class_serial = RCLASS_SERIAL(klass);
1384 st_add_direct(ivup->u.iv_index_tbl, (st_data_t)
id, (st_data_t)ent);
1385 ivup->iv_extended = 1;
1389generic_ivar_set(VALUE obj, ID
id, VALUE val)
1391 VALUE klass = rb_obj_class(obj);
1393 ivup.iv_extended = 0;
1394 ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
1398 iv_index_tbl_extend(&ivup,
id, klass);
1399 st_update(generic_ivtbl(obj,
id,
false), (st_data_t)obj, generic_ivar_update,
1404 ivup.u.ivtbl->ivptr[ivup.index] = val;
1410obj_ivar_heap_alloc(VALUE obj,
size_t newsize)
1412 VALUE *newptr = rb_transient_heap_alloc(obj,
sizeof(VALUE) * newsize);
1414 if (newptr != NULL) {
1415 ROBJ_TRANSIENT_SET(obj);
1418 ROBJ_TRANSIENT_UNSET(obj);
1419 newptr =
ALLOC_N(VALUE, newsize);
1425obj_ivar_heap_realloc(VALUE obj, int32_t len,
size_t newsize)
1430 if (ROBJ_TRANSIENT_P(obj)) {
1431 const VALUE *orig_ptr =
ROBJECT(obj)->as.heap.ivptr;
1432 newptr = obj_ivar_heap_alloc(obj, newsize);
1435 ROBJECT(obj)->as.heap.ivptr = newptr;
1436 for (i=0; i<(int)len; i++) {
1437 newptr[i] = orig_ptr[i];
1442 newptr =
ROBJECT(obj)->as.heap.ivptr;
1448#if USE_TRANSIENT_HEAP
1450rb_obj_transient_heap_evacuate(VALUE obj,
int promote)
1452 if (ROBJ_TRANSIENT_P(obj)) {
1458 new_ptr =
ALLOC_N(VALUE, len);
1459 ROBJ_TRANSIENT_UNSET(obj);
1462 new_ptr = obj_ivar_heap_alloc(obj, len);
1464 MEMCPY(new_ptr, old_ptr, VALUE, len);
1465 ROBJECT(obj)->as.heap.ivptr = new_ptr;
1471init_iv_list(VALUE obj, uint32_t len, uint32_t newsize,
st_table *index_tbl)
1476 if (
RBASIC(obj)->flags & ROBJECT_EMBED) {
1477 newptr = obj_ivar_heap_alloc(obj, newsize);
1478 MEMCPY(newptr, ptr, VALUE, len);
1479 RBASIC(obj)->flags &= ~ROBJECT_EMBED;
1480 ROBJECT(obj)->as.heap.ivptr = newptr;
1483 newptr = obj_ivar_heap_realloc(obj, len, newsize);
1486 for (; len < newsize; len++) {
1489 ROBJECT(obj)->as.heap.numiv = newsize;
1490 ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
1494rb_init_iv_list(VALUE obj)
1496 st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1497 uint32_t newsize = (uint32_t)index_tbl->num_entries;
1499 init_iv_list(obj, len, newsize, index_tbl);
1505obj_ensure_iv_index_mapping(VALUE obj, ID id)
1507 VALUE klass = rb_obj_class(obj);
1509 ivup.iv_extended = 0;
1510 ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
1514 iv_index_tbl_extend(&ivup,
id, klass);
1529rb_obj_ensure_iv_index_mapping(VALUE obj, ID
id)
1535 return (uint32_t)obj_ensure_iv_index_mapping(obj,
id).index;
1539obj_ivar_set(VALUE obj, ID
id, VALUE val)
1542 struct ivar_update ivup = obj_ensure_iv_index_mapping(obj,
id);
1545 if (len <= ivup.index) {
1546 uint32_t newsize = iv_index_tbl_newsize(&ivup);
1547 init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
1555ivar_set(VALUE obj, ID
id, VALUE val)
1557 RB_DEBUG_COUNTER_INC(ivar_set_base);
1561 obj_ivar_set(obj,
id, val);
1565 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1566 rb_class_ivar_set(obj,
id, val);
1569 generic_ivar_set(obj,
id, val);
1578 ivar_set(obj,
id, val);
1583rb_ivar_set_internal(VALUE obj, ID
id, VALUE val)
1588 ivar_set(obj,
id, val);
1601 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1602 if (iv_index_tbl_lookup(iv_index_tbl,
id, &index) &&
1610 if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)
id))
1615 return generic_ivar_defined(obj,
id);
1621typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
1622st_data_t rb_st_nth_key(
st_table *tab, st_index_t index);
1625iv_index_tbl_nth_id(
st_table *iv_index_tbl, uint32_t index)
1630 key = rb_st_nth_key(iv_index_tbl, index);
1637ivar_each_i(
st_table *iv_index_tbl, VALUE val, uint32_t i, rb_ivar_foreach_callback_func *func, st_data_t arg)
1640 ID
id = iv_index_tbl_nth_id(iv_index_tbl, i);
1641 switch (func(
id, val, arg)) {
1655obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1657 st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1658 if (!iv_index_tbl)
return;
1663 if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
1670gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1673 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1674 if (!iv_index_tbl)
return;
1675 if (!gen_ivtbl_get(obj, 0, &ivtbl))
return;
1677 for (uint32_t i=0; i<ivtbl->numiv; i++) {
1678 VALUE val = ivtbl->ivptr[i];
1679 if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
1693gen_ivar_copy(ID
id, VALUE val, st_data_t arg)
1698 ivup.iv_extended = 0;
1699 ivup.u.iv_index_tbl = c->iv_index_tbl;
1703 iv_index_tbl_extend(&ivup,
id, c->klass);
1707 if (ivup.index >= c->ivtbl->numiv) {
1708 uint32_t newsize = iv_index_tbl_newsize(&ivup);
1709 c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize);
1711 c->ivtbl->ivptr[ivup.index] = val;
1728 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1732 if (gen_ivtbl_count(ivtbl) == 0)
1735 if (gen_ivtbl_get(clone, 0, &c.ivtbl)) {
1736 for (i = 0; i < c.ivtbl->numiv; i++)
1737 c.ivtbl->ivptr[i] =
Qundef;
1740 c.ivtbl = gen_ivtbl_resize(0, ivtbl->numiv);
1744 VALUE klass = rb_obj_class(clone);
1745 c.iv_index_tbl = iv_index_tbl_make(clone, klass);
1748 gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c);
1755 generic_ivtbl_no_ractor_check(clone);
1756 st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)c.ivtbl);
1770rb_replace_generic_ivar(VALUE clone, VALUE obj)
1776 st_data_t ivtbl, obj_data = (st_data_t)obj;
1777 if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) {
1778 st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl);
1779 st_delete(generic_iv_tbl_, &obj_data, NULL);
1791rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1796 obj_ivar_each(obj, func, arg);
1800 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
1801 if (RCLASS_IV_TBL(obj)) {
1811 gen_ivar_each(obj, func, arg);
1826 if (ROBJECT_IV_INDEX_TBL(obj) != 0) {
1829 for (i = count = 0; i < num; ++i) {
1830 if (ivptr[i] !=
Qundef) {
1839 if ((tbl = RCLASS_IV_TBL(obj)) != 0) {
1840 return tbl->num_entries;
1847 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1848 return gen_ivtbl_count(ivtbl);
1857ivar_i(st_data_t k, st_data_t v, st_data_t a)
1860 VALUE ary = (
VALUE)a;
1895#define rb_is_constant_id rb_is_const_id
1896#define rb_is_constant_name rb_is_const_name
1897#define id_for_var(obj, name, part, type) \
1898 id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name")
1899#define id_for_var_message(obj, name, type, message) \
1900 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
1902check_id_type(VALUE obj, VALUE *pname,
1903 int (*valid_id_p)(ID),
int (*valid_name_p)(VALUE),
1904 const char *message,
size_t message_len)
1907 VALUE name = *pname;
1909 if (
id ? !valid_id_p(
id) : !valid_name_p(name)) {
1910 rb_name_err_raise_str(rb_fstring_new(message, message_len),
1944 const ID
id = id_for_var(obj, name, an, instance);
1956 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1957 if (iv_index_tbl_lookup(iv_index_tbl,
id, &index) &&
1966 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(
id);
1968 if (RCLASS_IV_TBL(obj) && lock_st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
1974 if (generic_ivar_remove(obj,
id, &val)) {
1982 rb_name_err_raise(
"instance variable %1$s not defined",
1987NORETURN(
static void uninitialized_constant(VALUE, VALUE));
1989uninitialized_constant(VALUE klass, VALUE name)
1992 rb_name_err_raise(
"uninitialized constant %2$s::%1$s",
1995 rb_name_err_raise(
"uninitialized constant %1$s",
2000rb_const_missing(VALUE klass, VALUE name)
2002 VALUE value =
rb_funcallv(klass, idConst_missing, 1, &name);
2003 rb_vm_inc_const_missing_count();
2045rb_mod_const_missing(VALUE klass, VALUE name)
2047 VALUE ref = GET_EC()->private_const_reference;
2048 rb_vm_pop_cfunc_frame();
2050 rb_name_err_raise(
"private constant %2$s::%1$s referenced",
2053 uninitialized_constant(klass, name);
2059autoload_mark(
void *ptr)
2065autoload_free(
void *ptr)
2071autoload_memsize(
const void *ptr)
2074 return st_memsize(tbl);
2078autoload_compact(
void *ptr)
2085 {autoload_mark, autoload_free, autoload_memsize, autoload_compact,},
2086 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2089#define check_autoload_table(av) \
2090 (struct st_table *)rb_check_typeddata((av), &autoload_data_type)
2093autoload_data(VALUE mod, ID
id)
2098 if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
2099 !(tbl = check_autoload_table((VALUE)val)) ||
2100 !st_lookup(tbl, (st_data_t)
id, &val)) {
2113 rb_const_flag_t flag;
2128 rb_serial_t fork_gen;
2133autoload_i_compact(
void *ptr)
2140autoload_i_mark(
void *ptr)
2147 if (list_empty(&p->constants)) {
2153autoload_i_free(
void *ptr)
2158 if (list_empty(&p->constants)) {
2164autoload_i_memsize(
const void *ptr)
2171 {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact},
2172 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2176autoload_c_compact(
void *ptr)
2187autoload_c_mark(
void *ptr)
2198autoload_c_free(
void *ptr)
2201 list_del(&ac->cnode);
2206autoload_c_memsize(
const void *ptr)
2213 {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
2214 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2220 struct autoload_const *ac = rb_check_typeddata(acv, &autoload_const_type);
2223 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2225 if (ele && ele->state && ele->fork_gen != GET_VM()->fork_gen) {
2233RUBY_FUNC_EXPORTED
void
2234rb_autoload(VALUE mod, ID
id,
const char *file)
2236 if (!file || !*file) {
2237 rb_raise(rb_eArgError,
"empty file name");
2239 rb_autoload_str(mod,
id, rb_fstring_cstr(file));
2243rb_autoload_str(VALUE mod, ID
id, VALUE file)
2252 rb_raise(rb_eNameError,
"autoload must be constant name: %"PRIsVALUE
"",
2258 rb_raise(rb_eArgError,
"empty file name");
2261 ce = rb_const_lookup(mod,
id);
2262 if (ce && ce->value !=
Qundef) {
2267 tbl = RCLASS_IV_TBL(mod);
2268 if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
2269 tbl = check_autoload_table((VALUE)av);
2272 if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
2274 st_add_direct(tbl, (st_data_t)autoload, av);
2276 DATA_PTR(av) = tbl = st_init_numtable();
2279 file = rb_fstring(file);
2280 if (!autoload_featuremap) {
2281 autoload_featuremap = rb_ident_hash_new();
2282 rb_obj_hide(autoload_featuremap);
2288 &autoload_data_i_type, ele);
2289 ele->feature = file;
2291 list_head_init(&ele->constants);
2295 ele = rb_check_typeddata(ad, &autoload_data_i_type);
2301 &autoload_const_type, ac);
2305 ac->flag = CONST_PUBLIC;
2307 list_add_tail(&ele->constants, &ac->cnode);
2308 st_insert(tbl, (st_data_t)
id, (st_data_t)acv);
2313autoload_delete(VALUE mod, ID
id)
2315 st_data_t val, load = 0, n = id;
2317 if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
2318 struct st_table *tbl = check_autoload_table((VALUE)val);
2322 st_delete(tbl, &n, &load);
2325 ele = get_autoload_data((VALUE)load, &ac);
2328 VM_ASSERT(!list_empty(&ele->constants));
2336 list_del_init(&ac->cnode);
2338 if (tbl->num_entries == 0) {
2340 st_delete(RCLASS_IV_TBL(mod), &n, &val);
2347check_autoload_required(VALUE mod, ID
id,
const char **loadingpath)
2350 VALUE load = autoload_data(mod,
id);
2352 const char *loading;
2354 if (!load || !(ele = get_autoload_data(load, 0))) {
2357 file = ele->feature;
2360 rb_raise(rb_eArgError,
"empty file name");
2377 if (loadingpath && loading) {
2378 *loadingpath = loading;
2384static struct autoload_const *autoloading_const_entry(VALUE mod, ID
id);
2386MJIT_FUNC_EXPORTED
int
2387rb_autoloading_value(VALUE mod, ID
id, VALUE* value, rb_const_flag_t *flag)
2390 if (!ac)
return FALSE;
2402autoloading_const_entry(VALUE mod, ID
id)
2404 VALUE load = autoload_data(mod,
id);
2408 if (!load || !(ele = get_autoload_data(load, &ac))) {
2413 if (ac->value !=
Qundef) {
2421autoload_defined_p(VALUE mod, ID
id)
2425 if (!ce || ce->value !=
Qundef) {
2428 return !rb_autoloading_value(mod,
id, NULL, NULL);
2436 VALUE klass = ac->mod;
2438 check_before_mod_set(klass,
id, ac->value,
"constant");
2442 const_tbl_update(ac);
2450autoload_require(VALUE arg)
2456 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2461 return state->result;
2465autoload_reset(VALUE arg)
2468 int need_wakeups = 0;
2472 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2473 if (ele->state == state) {
2480 if (
RTEST(state->result)) {
2483 list_for_each_safe(&ele->constants, ac, next, cnode) {
2484 if (ac->value !=
Qundef) {
2485 autoload_const_set(ac);
2494 list_for_each_safe(&state->waitq, cur, nxt, waitq.n) {
2495 VALUE th = cur->thread;
2498 list_del_init(&cur->waitq.n);
2512autoload_sleep(VALUE arg)
2522 }
while (state->thread !=
Qfalse);
2528autoload_sleep_done(VALUE arg)
2532 if (state->thread !=
Qfalse && rb_thread_to_be_killed(state->thread)) {
2533 list_del(&state->waitq.n);
2543 const char *loading = 0, *src;
2550 if (!autoload_defined_p(mod,
id))
return Qfalse;
2551 load = check_autoload_required(mod,
id, &loading);
2552 if (!load)
return Qfalse;
2554 if (src && loading && strcmp(src, loading) == 0)
return Qfalse;
2556 if (UNLIKELY(!rb_ractor_main_p())) {
2557 rb_raise(rb_eRactorUnsafeError,
"require by autoload on non-main Ractor is not supported (%s)",
rb_id2name(
id));
2560 if ((ce = rb_const_lookup(mod,
id))) {
2561 flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2565 if (!(ele = get_autoload_data(load, &ac))) {
2571 ele->state = &state;
2572 ele->fork_gen = GET_VM()->fork_gen;
2578 list_head_init(&state.waitq);
2580 else if (state.thread == ele->state->thread) {
2584 list_add_tail(&ele->state->waitq, &state.waitq.n);
2586 rb_ensure(autoload_sleep, (VALUE)&state,
2587 autoload_sleep_done, (VALUE)&state);
2592 result =
rb_ensure(autoload_require, (VALUE)&state,
2593 autoload_reset, (VALUE)&state);
2595 if (!(ce = rb_const_lookup(mod,
id)) || ce->value ==
Qundef) {
2598 else if (flag > 0) {
2608 return rb_autoload_at_p(mod,
id, TRUE);
2612rb_autoload_at_p(VALUE mod, ID
id,
int recur)
2617 while (!autoload_defined_p(mod,
id)) {
2618 if (!recur)
return Qnil;
2620 if (!mod)
return Qnil;
2622 load = check_autoload_required(mod,
id, 0);
2623 if (!load)
return Qnil;
2624 return (ele = get_autoload_data(load, 0)) ? ele->feature :
Qnil;
2627MJIT_FUNC_EXPORTED
void
2630 if (RB_CONST_DEPRECATED_P(ce) &&
2632 if (klass == rb_cObject) {
2643rb_const_get_0(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
2645 VALUE c = rb_const_search(klass,
id, exclude, recurse, visibility);
2647 if (UNLIKELY(!rb_ractor_main_p())) {
2649 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));
2654 return rb_const_missing(klass,
ID2SYM(
id));
2658rb_const_search_from(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
2660 VALUE value, current;
2661 bool first_iteration =
true;
2663 for (current = klass;
2665 current =
RCLASS_SUPER(current), first_iteration =
false) {
2670 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
2683 while ((ce = rb_const_lookup(tmp,
id))) {
2684 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2685 GET_EC()->private_const_reference = tmp;
2688 rb_const_warn_if_deprecated(ce, tmp,
id);
2692 if (am == tmp)
break;
2694 ac = autoloading_const_entry(tmp,
id);
2695 if (ac)
return ac->value;
2699 if (exclude && tmp == rb_cObject) {
2704 if (!recurse)
break;
2708 GET_EC()->private_const_reference = 0;
2713rb_const_search(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
2717 if (klass == rb_cObject) exclude = FALSE;
2718 value = rb_const_search_from(klass,
id, exclude, recurse, visibility);
2719 if (value !=
Qundef)
return value;
2720 if (exclude)
return value;
2723 return rb_const_search_from(rb_cObject,
id, FALSE, recurse, visibility);
2729 return rb_const_get_0(klass,
id, TRUE, TRUE, FALSE);
2735 return rb_const_get_0(klass,
id, FALSE, TRUE, FALSE);
2741 return rb_const_get_0(klass,
id, TRUE, FALSE, FALSE);
2744MJIT_FUNC_EXPORTED VALUE
2745rb_public_const_get_from(VALUE klass, ID
id)
2747 return rb_const_get_0(klass,
id, TRUE, TRUE, TRUE);
2750MJIT_FUNC_EXPORTED VALUE
2751rb_public_const_get_at(VALUE klass, ID
id)
2753 return rb_const_get_0(klass,
id, TRUE, FALSE, TRUE);
2756NORETURN(
static void undefined_constant(VALUE mod, VALUE name));
2758undefined_constant(VALUE mod, VALUE name)
2760 rb_name_err_raise(
"constant %2$s::%1$s not defined",
2765rb_const_location_from(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
2767 while (
RTEST(klass)) {
2770 while ((ce = rb_const_lookup(klass,
id))) {
2771 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2774 if (exclude && klass == rb_cObject) {
2780 if (!recurse)
break;
2789rb_const_location(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
2793 if (klass == rb_cObject) exclude = FALSE;
2794 loc = rb_const_location_from(klass,
id, exclude, recurse, visibility);
2795 if (!
NIL_P(loc))
return loc;
2796 if (exclude)
return loc;
2799 return rb_const_location_from(rb_cObject,
id, FALSE, recurse, visibility);
2803rb_const_source_location(VALUE klass, ID
id)
2805 return rb_const_location(klass,
id, FALSE, TRUE, FALSE);
2808MJIT_FUNC_EXPORTED VALUE
2809rb_const_source_location_at(VALUE klass, ID
id)
2811 return rb_const_location(klass,
id, TRUE, FALSE, FALSE);
2827 const ID
id = id_for_var(mod, name, a, constant);
2830 undefined_constant(mod, name);
2842 ce = rb_const_lookup(mod,
id);
2843 if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod),
id)) {
2845 rb_name_err_raise(
"cannot remove %2$s::%1$s",
2848 undefined_constant(mod,
ID2SYM(
id));
2855 autoload_delete(mod,
id);
2863cv_i_update(st_data_t *k, st_data_t *v, st_data_t a,
int existing)
2865 if (existing)
return ST_STOP;
2870static enum rb_id_table_iterator_result
2871sv_i(ID key, VALUE v,
void *a)
2877 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2879 return ID_TABLE_CONTINUE;
2882static enum rb_id_table_iterator_result
2883rb_local_constants_i(ID const_name, VALUE const_value,
void *ary)
2888 return ID_TABLE_CONTINUE;
2892rb_local_constants(VALUE mod)
2902 rb_id_table_foreach(tbl, rb_local_constants_i, (
void *)ary);
2914 tbl = st_init_numtable();
2916 if (RCLASS_CONST_TBL(mod)) {
2919 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
2934 if (tmp == rb_cObject && mod != rb_cObject)
break;
2940list_i(st_data_t key, st_data_t value, VALUE ary)
2983 bool inherit =
true;
2991 return rb_local_constants(mod);
2996rb_const_defined_0(VALUE klass, ID
id,
int exclude,
int recurse,
int visibility)
3005 if ((ce = rb_const_lookup(tmp,
id))) {
3006 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3009 if (ce->value ==
Qundef && !check_autoload_required(tmp,
id, 0) &&
3010 !rb_autoloading_value(tmp,
id, NULL, NULL))
3013 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3019 if (!recurse)
break;
3033 return rb_const_defined_0(klass,
id, TRUE, TRUE, FALSE);
3039 return rb_const_defined_0(klass,
id, FALSE, TRUE, FALSE);
3045 return rb_const_defined_0(klass,
id, TRUE, FALSE, FALSE);
3048MJIT_FUNC_EXPORTED
int
3049rb_public_const_defined_from(VALUE klass, ID
id)
3051 return rb_const_defined_0(klass,
id, TRUE, TRUE, TRUE);
3055check_before_mod_set(VALUE klass, ID
id, VALUE val,
const char *dest)
3060static void set_namespace_path(VALUE named_namespace, VALUE name);
3062static enum rb_id_table_iterator_result
3063set_namespace_path_i(ID
id, VALUE v,
void *payload)
3066 VALUE value = ce->value;
3067 int has_permanent_classpath;
3068 VALUE parental_path = *((VALUE *) payload);
3070 return ID_TABLE_CONTINUE;
3072 classname(value, &has_permanent_classpath);
3073 if (has_permanent_classpath) {
3074 return ID_TABLE_CONTINUE;
3076 set_namespace_path(value, build_const_path(parental_path,
id));
3077 if (RCLASS_IV_TBL(value)) {
3078 st_data_t tmp = tmp_classpath;
3079 st_delete(RCLASS_IV_TBL(value), &tmp, 0);
3082 return ID_TABLE_CONTINUE;
3091set_namespace_path(VALUE named_namespace, VALUE namespace_path)
3093 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3097 rb_class_ivar_set(named_namespace, classpath, namespace_path);
3099 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3111 rb_raise(rb_eTypeError,
"no class/module to define constant %"PRIsVALUE
"",
3116 rb_raise(rb_eRactorIsolationError,
"can not set constants with non-shareable objects by non-main Ractors");
3119 check_before_mod_set(klass,
id, val,
"constant");
3123 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3125 RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
3128 rb_id_table_insert(tbl,
id, (VALUE)ce);
3129 setup_const_entry(ce, klass, val, CONST_PUBLIC);
3133 .mod = klass, .id = id,
3134 .value = val, .flag = CONST_PUBLIC,
3137 const_tbl_update(&ac);
3146 if (rb_cObject && rb_namespace_p(val)) {
3147 int val_path_permanent;
3148 VALUE val_path = classname(val, &val_path_permanent);
3149 if (
NIL_P(val_path) || !val_path_permanent) {
3150 if (klass == rb_cObject) {
3154 int parental_path_permanent;
3155 VALUE parental_path = classname(klass, &parental_path_permanent);
3156 if (
NIL_P(parental_path)) {
3158 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
3160 if (parental_path_permanent && !val_path_permanent) {
3161 set_namespace_path(val, build_const_path(parental_path,
id));
3163 else if (!parental_path_permanent &&
NIL_P(val_path)) {
3164 ivar_set(val, tmp_classpath, build_const_path(parental_path,
id));
3172current_autoload_data(VALUE mod, ID
id,
struct autoload_const **acp)
3175 VALUE load = autoload_data(mod,
id);
3176 if (!load)
return 0;
3177 ele = get_autoload_data(load, acp);
3190 VALUE klass = ac->mod;
3191 VALUE val = ac->value;
3193 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3194 rb_const_flag_t visibility = ac->flag;
3197 if (rb_id_table_lookup(tbl,
id, &value)) {
3199 if (ce->value ==
Qundef) {
3206 ac->file = rb_source_location(&ac->line);
3210 autoload_delete(klass,
id);
3211 ce->flag = visibility;
3214 ce->line = ac->line;
3219 VALUE name = QUOTE_ID(
id);
3220 visibility = ce->flag;
3221 if (klass == rb_cObject)
3222 rb_warn(
"already initialized constant %"PRIsVALUE
"", name);
3224 rb_warn(
"already initialized constant %"PRIsVALUE
"::%"PRIsVALUE
"",
3226 if (!
NIL_P(ce->file) && ce->line) {
3228 "previous definition of %"PRIsVALUE
" was here", name);
3232 setup_const_entry(ce, klass, val, visibility);
3238 rb_id_table_insert(tbl,
id, (VALUE)ce);
3239 setup_const_entry(ce, klass, val, visibility);
3245 rb_const_flag_t visibility)
3247 ce->flag = visibility;
3249 RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
3258 rb_warn(
"rb_define_const: invalid name `%s' for constant", name);
3271set_const_visibility(VALUE mod,
int argc,
const VALUE *argv,
3272 rb_const_flag_t flag, rb_const_flag_t mask)
3280 rb_warning(
"%"PRIsVALUE
" with no argument is just ignored",
3285 for (i = 0; i < argc; i++) {
3287 VALUE val = argv[i];
3294 undefined_constant(mod, val);
3296 if ((ce = rb_const_lookup(mod,
id))) {
3299 if (ce->value ==
Qundef) {
3302 ele = current_autoload_data(mod,
id, &ac);
3313 undefined_constant(mod,
ID2SYM(
id));
3324 long len = strlen(name);
3328 undefined_constant(mod, rb_fstring_new(name, len));
3330 if (!(ce = rb_const_lookup(mod,
id))) {
3331 undefined_constant(mod,
ID2SYM(
id));
3333 ce->flag |= CONST_DEPRECATED;
3344rb_mod_private_constant(
int argc,
const VALUE *argv, VALUE obj)
3346 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
3358rb_mod_public_constant(
int argc,
const VALUE *argv, VALUE obj)
3360 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
3384rb_mod_deprecate_constant(
int argc,
const VALUE *argv, VALUE obj)
3386 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3391original_module(VALUE c)
3399cvar_lookup_at(VALUE klass, ID
id, st_data_t *v)
3401 if (!RCLASS_IV_TBL(klass))
return 0;
3402 return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)
id, v);
3406cvar_front_klass(VALUE klass)
3410 if (rb_namespace_p(obj)) {
3418cvar_overtaken(VALUE front, VALUE target, ID
id)
3420 if (front && target != front) {
3421 st_data_t did = (st_data_t)
id;
3423 if (original_module(front) != original_module(target)) {
3425 "class variable % "PRIsVALUE
" of %"PRIsVALUE
" is overtaken by %"PRIsVALUE
"",
3430 st_delete(RCLASS_IV_TBL(front), &did, 0);
3436find_cvar(VALUE klass, VALUE * front, VALUE * target, ID
id)
3439 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR();
3440 if (cvar_lookup_at(klass,
id, (&v))) {
3447 for (klass = cvar_front_klass(klass); klass; klass =
RCLASS_SUPER(klass)) {
3448 if (cvar_lookup_at(klass,
id, (&v))) {
3459#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3460 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3461 if (cvar_lookup_at(klass, id, (v))) { \
3466#define CVAR_LOOKUP(v,r) do {\
3467 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
3468 if (cvar_lookup_at(klass, id, (v))) {r;}\
3469 CVAR_FOREACH_ANCESTORS(klass, v, r);\
3473check_for_cvar_table(VALUE subclass, VALUE key)
3475 st_table *tbl = RCLASS_IV_TBL(subclass);
3477 if (tbl && st_lookup(tbl, key, NULL)) {
3478 RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
3479 ruby_vm_global_cvar_state++;
3483 rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
3489 VALUE tmp, front = 0, target = 0;
3492 CVAR_LOOKUP(0, {
if (!front) front = klass; target = klass;});
3494 cvar_overtaken(front, target,
id);
3501 target =
RBASIC(target)->klass;
3503 check_before_mod_set(target,
id, val,
"class variable");
3505 int result = rb_class_ivar_set(target,
id, val);
3507 struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
3510 rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
3516 if (!rb_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
3518 ent->class_value = target;
3519 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3520 rb_id_table_insert(rb_cvc_tbl,
id, (VALUE)ent);
3521 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
3524 ent = (
void *)ent_data;
3525 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3533 if (RCLASS_SUBCLASSES(target)) {
3534 rb_class_foreach_subclass(target, check_for_cvar_table,
id);
3546 value = find_cvar(klass, front, &target,
id);
3548 rb_name_err_raise(
"uninitialized class variable %1$s in %2$s",
3551 cvar_overtaken(*front, target,
id);
3552 return (VALUE)value;
3565 if (!klass)
return Qfalse;
3566 CVAR_LOOKUP(0,
return Qtrue);
3571cv_intern(VALUE klass,
const char *name)
3575 rb_name_err_raise(
"wrong class variable name %1$s",
3584 ID
id = cv_intern(klass, name);
3591 ID
id = cv_intern(klass, name);
3602cv_i(st_data_t k, st_data_t v, st_data_t a)
3608 st_update(tbl, (st_data_t)key, cv_i_update, 0);
3614mod_cvar_at(VALUE mod,
void *data)
3618 tbl = st_init_numtable();
3620 if (RCLASS_IV_TBL(mod)) {
3627mod_cvar_of(VALUE mod,
void *data)
3631 if (rb_namespace_p(
rb_ivar_get(mod, id__attached__))) {
3632 data = mod_cvar_at(tmp, data);
3633 tmp = cvar_front_klass(tmp);
3637 data = mod_cvar_at(tmp, data);
3645cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3653cvar_list(
void *data)
3689 bool inherit =
true;
3694 tbl = mod_cvar_of(mod, 0);
3697 tbl = mod_cvar_at(mod, 0);
3699 return cvar_list(tbl);
3724 const ID
id = id_for_var_message(mod, name,
class,
"wrong class variable name %1$s");
3725 st_data_t val, n = id;
3731 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
3735 rb_name_err_raise(
"cannot remove %1$s for %2$s", mod,
ID2SYM(
id));
3738 rb_name_err_raise(
"class variable %1$s not defined for %2$s",
3764rb_class_ivar_set(VALUE obj, ID key, VALUE value)
3766 if (!RCLASS_IV_TBL(obj)) {
3767 RCLASS_IV_TBL(obj) = st_init_numtable();
3770 st_table *tbl = RCLASS_IV_TBL(obj);
3771 int result = lock_st_insert(tbl, (st_data_t)key, (st_data_t)value);
3777tbl_copy_i(st_data_t key, st_data_t value, st_data_t data)
3784rb_iv_tbl_copy(VALUE dst, VALUE src)
3786 st_table *orig_tbl = RCLASS_IV_TBL(src);
3787 st_table *new_tbl = st_copy(orig_tbl);
3788 st_foreach(new_tbl, tbl_copy_i, (st_data_t)dst);
3789 RCLASS_IV_TBL(dst) = new_tbl;
3793rb_const_lookup(VALUE klass, ID
id)
3795 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3802 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.
static VALUE RB_OBJ_FROZEN_RAW(VALUE obj)
This is an implenentation detail of RB_OBJ_FROZEN().
void rb_class_modify_check(VALUE)
Asserts that klass is not a frozen class.
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 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 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_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 ALLOCV_END
Old name of RB_ALLOCV_END.
void rb_category_warn(rb_warning_category_t cat, 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_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_warning(const char *fmt,...)
Issues a warning.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
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.
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
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_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
VALUE rb_ary_new(void)
Allocates a new, 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.
#define rb_check_frozen
Just another name of rb_check_frozen.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
ID rb_frame_callee(void)
Identical to rb_frame_this_func(), except it returns the named used to call the method.
void rb_gc_mark(VALUE obj)
Marks an object.
void rb_mark_tbl_no_pin(struct st_table *tbl)
Identical to rb_mark_tbl(), except it marks objects using rb_gc_mark_movable().
void rb_gc_mark_movable(VALUE obj)
Maybe this is the only function provided for C extensions to control the pinning of objects,...
void rb_gc_mark_maybe(VALUE obj)
Identical to rb_gc_mark(), except it allows the passed value be a non-object.
VALUE rb_gc_location(VALUE obj)
Finds a new "location" of an object.
void rb_gc_update_tbl_refs(st_table *ptr)
Updates references inside of tables.
#define st_foreach_safe
Just another name of rb_st_foreach_safe.
VALUE rb_hash_delete(VALUE hash, VALUE key)
Deletes the passed key from the passed hash table, if any.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
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_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
VALUE rb_str_new_cstr(const char *ptr)
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.
void rb_thread_sleep_deadly(void)
Identical to rb_thread_sleep_forever(), except the thread calling this function is considered "dead" ...
VALUE rb_thread_current(void)
Obtains the "current" thread.
VALUE rb_thread_wakeup_alive(VALUE thread)
Identical to rb_thread_wakeup(), except it doesn't raise on an already killed thread.
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_ivar_foreach(VALUE obj, int(*func)(ID name, VALUE val, st_data_t arg), st_data_t arg)
Iterates over an object's instance variables.
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(void)
Clears the constant cache.
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.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
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.
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
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_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
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.
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Identical to rb_define_virtual_variable(), but can also specify a storage.
rb_gvar_getter_t rb_gvar_var_getter
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.
int st_foreach(st_table *q, int_type *w, st_data_t e)
Iteration over the given table.
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#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.
static uint32_t ROBJECT_NUMIV(VALUE obj)
Queries the number of instance variables.
static VALUE * ROBJECT_IVPTR(VALUE obj)
Queries the instance variables.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
#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.
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_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.