Ruby 3.2.1p31 (2023-02-08 revision 31819e82c88c6f8ecfaeb162519bfa26a14b21fd)
variable.c
1/**********************************************************************
2
3 variable.c -
4
5 $Author$
6 created at: Tue Apr 19 23:55:15 JST 1994
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12**********************************************************************/
13
14#include "ruby/internal/config.h"
15#include <stddef.h>
17#include "ccan/list/list.h"
18#include "constant.h"
19#include "debug_counter.h"
20#include "id.h"
21#include "id_table.h"
22#include "internal.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"
33#include "ruby/encoding.h"
34#include "ruby/st.h"
35#include "ruby/util.h"
36#include "transient_heap.h"
37#include "shape.h"
38#include "variable.h"
39#include "vm_core.h"
40#include "ractor_core.h"
41#include "vm_sync.h"
42
43RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
44#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
45
46typedef void rb_gvar_compact_t(void *var);
47
48static struct rb_id_table *rb_global_tbl;
49static ID autoload, classpath, tmp_classpath;
50
51// This hash table maps file paths to loadable features. We use this to track
52// autoload state until it's no longer needed.
53// feature (file path) => struct autoload_data
54static VALUE autoload_features;
55
56// This mutex is used to protect autoloading state. We use a global mutex which
57// is held until a per-feature mutex can be created. This ensures there are no
58// race conditions relating to autoload state.
59static VALUE autoload_mutex;
60
61static void check_before_mod_set(VALUE, ID, VALUE, const char *);
62static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
63static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
64static st_table *generic_iv_tbl_;
65
67 struct gen_ivtbl *ivtbl;
68 uint32_t iv_index;
69 rb_shape_t* shape;
70};
71
72void
73Init_var_tables(void)
74{
75 rb_global_tbl = rb_id_table_create(0);
76 generic_iv_tbl_ = st_init_numtable();
77 autoload = rb_intern_const("__autoload__");
78 /* __classpath__: fully qualified class path */
79 classpath = rb_intern_const("__classpath__");
80 /* __tmp_classpath__: temporary class path which contains anonymous names */
81 tmp_classpath = rb_intern_const("__tmp_classpath__");
82
83 autoload_mutex = rb_mutex_new();
84 rb_obj_hide(autoload_mutex);
85 rb_gc_register_mark_object(autoload_mutex);
86
87 autoload_features = rb_ident_hash_new();
88 rb_obj_hide(autoload_features);
89 rb_gc_register_mark_object(autoload_features);
90}
91
92static inline bool
93rb_namespace_p(VALUE obj)
94{
95 if (RB_SPECIAL_CONST_P(obj)) return false;
96 switch (RB_BUILTIN_TYPE(obj)) {
97 case T_MODULE: case T_CLASS: return true;
98 default: break;
99 }
100 return false;
101}
102
111static VALUE
112classname(VALUE klass, int *permanent)
113{
114 *permanent = 0;
115 if (!RCLASS_EXT(klass)) return Qnil;
116
117 VALUE classpathv = rb_ivar_lookup(klass, classpath, Qnil);
118 if (RTEST(classpathv)) {
119 *permanent = 1;
120 return classpathv;
121 }
122
123 return rb_ivar_lookup(klass, tmp_classpath, Qnil);;
124}
125
126/*
127 * call-seq:
128 * mod.name -> string
129 *
130 * Returns the name of the module <i>mod</i>. Returns nil for anonymous modules.
131 */
132
133VALUE
135{
136 int permanent;
137 return classname(mod, &permanent);
138}
139
140static VALUE
141make_temporary_path(VALUE obj, VALUE klass)
142{
143 VALUE path;
144 switch (klass) {
145 case Qnil:
146 path = rb_sprintf("#<Class:%p>", (void*)obj);
147 break;
148 case Qfalse:
149 path = rb_sprintf("#<Module:%p>", (void*)obj);
150 break;
151 default:
152 path = rb_sprintf("#<%"PRIsVALUE":%p>", klass, (void*)obj);
153 break;
154 }
155 OBJ_FREEZE(path);
156 return path;
157}
158
159typedef VALUE (*fallback_func)(VALUE obj, VALUE name);
160
161static VALUE
162rb_tmp_class_path(VALUE klass, int *permanent, fallback_func fallback)
163{
164 VALUE path = classname(klass, permanent);
165
166 if (!NIL_P(path)) {
167 return path;
168 }
169 else {
170 if (RB_TYPE_P(klass, T_MODULE)) {
171 if (rb_obj_class(klass) == rb_cModule) {
172 path = Qfalse;
173 }
174 else {
175 int perm;
176 path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, fallback);
177 }
178 }
179 *permanent = 0;
180 return fallback(klass, path);
181 }
182}
183
184VALUE
186{
187 int permanent;
188 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
189 if (!NIL_P(path)) path = rb_str_dup(path);
190 return path;
191}
192
193VALUE
195{
196 return rb_mod_name(klass);
197}
198
199static VALUE
200no_fallback(VALUE obj, VALUE name)
201{
202 return name;
203}
204
205VALUE
206rb_search_class_path(VALUE klass)
207{
208 int permanent;
209 return rb_tmp_class_path(klass, &permanent, no_fallback);
210}
211
212static VALUE
213build_const_pathname(VALUE head, VALUE tail)
214{
215 VALUE path = rb_str_dup(head);
216 rb_str_cat2(path, "::");
217 rb_str_append(path, tail);
218 return rb_fstring(path);
219}
220
221static VALUE
222build_const_path(VALUE head, ID tail)
223{
224 return build_const_pathname(head, rb_id2str(tail));
225}
226
227void
229{
230 VALUE str;
231 ID pathid = classpath;
232
233 if (under == rb_cObject) {
234 str = rb_str_new_frozen(name);
235 }
236 else {
237 int permanent;
238 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
239 str = build_const_pathname(str, name);
240 if (!permanent) {
241 pathid = tmp_classpath;
242 }
243 }
244 rb_ivar_set(klass, pathid, str);
245}
246
247void
248rb_set_class_path(VALUE klass, VALUE under, const char *name)
249{
250 VALUE str = rb_str_new2(name);
251 OBJ_FREEZE(str);
252 rb_set_class_path_string(klass, under, str);
253}
254
255VALUE
257{
258 rb_encoding *enc = rb_enc_get(pathname);
259 const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
260 ID id;
261 VALUE c = rb_cObject;
262
263 if (!rb_enc_asciicompat(enc)) {
264 rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
265 }
266 pbeg = p = path;
267 pend = path + RSTRING_LEN(pathname);
268 if (path == pend || path[0] == '#') {
269 rb_raise(rb_eArgError, "can't retrieve anonymous class %"PRIsVALUE,
270 QUOTE(pathname));
271 }
272 while (p < pend) {
273 while (p < pend && *p != ':') p++;
274 id = rb_check_id_cstr(pbeg, p-pbeg, enc);
275 if (p < pend && p[0] == ':') {
276 if ((size_t)(pend - p) < 2 || p[1] != ':') goto undefined_class;
277 p += 2;
278 pbeg = p;
279 }
280 if (!id) {
281 goto undefined_class;
282 }
283 c = rb_const_search(c, id, TRUE, FALSE, FALSE);
284 if (UNDEF_P(c)) goto undefined_class;
285 if (!rb_namespace_p(c)) {
286 rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
287 pathname);
288 }
289 }
290 RB_GC_GUARD(pathname);
291
292 return c;
293
294 undefined_class:
295 rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE,
296 rb_str_subseq(pathname, 0, p-path));
298}
299
300VALUE
301rb_path2class(const char *path)
302{
303 return rb_path_to_class(rb_str_new_cstr(path));
304}
305
306VALUE
308{
309 return rb_class_path(rb_class_real(klass));
310}
311
312const char *
314{
315 int permanent;
316 VALUE path = rb_tmp_class_path(rb_class_real(klass), &permanent, make_temporary_path);
317 if (NIL_P(path)) return NULL;
318 return RSTRING_PTR(path);
319}
320
321const char *
323{
324 return rb_class2name(CLASS_OF(obj));
325}
326
327struct trace_var {
328 int removed;
329 void (*func)(VALUE arg, VALUE val);
330 VALUE data;
331 struct trace_var *next;
332};
333
335 int counter;
336 int block_trace;
337 VALUE *data;
338 rb_gvar_getter_t *getter;
339 rb_gvar_setter_t *setter;
340 rb_gvar_marker_t *marker;
341 rb_gvar_compact_t *compactor;
342 struct trace_var *trace;
343};
344
346 struct rb_global_variable *var;
347 ID id;
348 bool ractor_local;
349};
350
351static struct rb_global_entry*
352rb_find_global_entry(ID id)
353{
354 struct rb_global_entry *entry;
355 VALUE data;
356
357 if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
358 entry = NULL;
359 }
360 else {
361 entry = (struct rb_global_entry *)data;
362 RUBY_ASSERT(entry != NULL);
363 }
364
365 if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
366 rb_raise(rb_eRactorIsolationError, "can not access global variables %s from non-main Ractors", rb_id2name(id));
367 }
368
369 return entry;
370}
371
372void
373rb_gvar_ractor_local(const char *name)
374{
375 struct rb_global_entry *entry = rb_find_global_entry(rb_intern(name));
376 entry->ractor_local = true;
377}
378
379static void
380rb_gvar_undef_compactor(void *var)
381{
382}
383
384static struct rb_global_entry*
386{
387 struct rb_global_entry *entry = rb_find_global_entry(id);
388 if (!entry) {
389 struct rb_global_variable *var;
390 entry = ALLOC(struct rb_global_entry);
391 var = ALLOC(struct rb_global_variable);
392 entry->id = id;
393 entry->var = var;
394 entry->ractor_local = false;
395 var->counter = 1;
396 var->data = 0;
397 var->getter = rb_gvar_undef_getter;
398 var->setter = rb_gvar_undef_setter;
399 var->marker = rb_gvar_undef_marker;
400 var->compactor = rb_gvar_undef_compactor;
401
402 var->block_trace = 0;
403 var->trace = 0;
404 rb_id_table_insert(rb_global_tbl, id, (VALUE)entry);
405 }
406 return entry;
407}
408
409VALUE
411{
412 rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id));
413
414 return Qnil;
415}
416
417static void
418rb_gvar_val_compactor(void *_var)
419{
420 struct rb_global_variable *var = (struct rb_global_variable *)_var;
421
422 VALUE obj = (VALUE)var->data;
423
424 if (obj) {
425 VALUE new = rb_gc_location(obj);
426 if (new != obj) {
427 var->data = (void*)new;
428 }
429 }
430}
431
432void
434{
435 struct rb_global_variable *var = rb_global_entry(id)->var;
436 var->getter = rb_gvar_val_getter;
437 var->setter = rb_gvar_val_setter;
438 var->marker = rb_gvar_val_marker;
439 var->compactor = rb_gvar_val_compactor;
440
441 var->data = (void*)val;
442}
443
444void
446{
447}
448
449VALUE
450rb_gvar_val_getter(ID id, VALUE *data)
451{
452 return (VALUE)data;
453}
454
455void
457{
458 struct rb_global_variable *var = rb_global_entry(id)->var;
459 var->data = (void*)val;
460}
461
462void
464{
465 VALUE data = (VALUE)var;
466 if (data) rb_gc_mark_movable(data);
467}
468
469VALUE
471{
472 if (!var) return Qnil;
473 return *var;
474}
475
476void
477rb_gvar_var_setter(VALUE val, ID id, VALUE *data)
478{
479 *data = val;
480}
481
482void
484{
485 if (var) rb_gc_mark_maybe(*var);
486}
487
488void
490{
491 rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id));
492}
493
494static enum rb_id_table_iterator_result
495mark_global_entry(VALUE v, void *ignored)
496{
497 struct rb_global_entry *entry = (struct rb_global_entry *)v;
498 struct trace_var *trace;
499 struct rb_global_variable *var = entry->var;
500
501 (*var->marker)(var->data);
502 trace = var->trace;
503 while (trace) {
504 if (trace->data) rb_gc_mark_maybe(trace->data);
505 trace = trace->next;
506 }
507 return ID_TABLE_CONTINUE;
508}
509
510void
511rb_gc_mark_global_tbl(void)
512{
513 if (rb_global_tbl) {
514 rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
515 }
516}
517
518static enum rb_id_table_iterator_result
519update_global_entry(VALUE v, void *ignored)
520{
521 struct rb_global_entry *entry = (struct rb_global_entry *)v;
522 struct rb_global_variable *var = entry->var;
523
524 (*var->compactor)(var);
525 return ID_TABLE_CONTINUE;
526}
527
528void
529rb_gc_update_global_tbl(void)
530{
531 if (rb_global_tbl) {
532 rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
533 }
534}
535
536static ID
537global_id(const char *name)
538{
539 ID id;
540
541 if (name[0] == '$') id = rb_intern(name);
542 else {
543 size_t len = strlen(name);
544 VALUE vbuf = 0;
545 char *buf = ALLOCV_N(char, vbuf, len+1);
546 buf[0] = '$';
547 memcpy(buf+1, name, len);
548 id = rb_intern2(buf, len+1);
549 ALLOCV_END(vbuf);
550 }
551 return id;
552}
553
554static ID
555find_global_id(const char *name)
556{
557 ID id;
558 size_t len = strlen(name);
559
560 if (name[0] == '$') {
561 id = rb_check_id_cstr(name, len, NULL);
562 }
563 else {
564 VALUE vbuf = 0;
565 char *buf = ALLOCV_N(char, vbuf, len+1);
566 buf[0] = '$';
567 memcpy(buf+1, name, len);
568 id = rb_check_id_cstr(buf, len+1, NULL);
569 ALLOCV_END(vbuf);
570 }
571
572 return id;
573}
574
575void
577 const char *name,
578 VALUE *var,
579 rb_gvar_getter_t *getter,
580 rb_gvar_setter_t *setter)
581{
582 volatile VALUE tmp = var ? *var : Qnil;
583 ID id = global_id(name);
584 struct rb_global_variable *gvar = rb_global_entry(id)->var;
585
586 gvar->data = (void*)var;
587 gvar->getter = getter ? (rb_gvar_getter_t *)getter : rb_gvar_var_getter;
588 gvar->setter = setter ? (rb_gvar_setter_t *)setter : rb_gvar_var_setter;
589 gvar->marker = rb_gvar_var_marker;
590
591 RB_GC_GUARD(tmp);
592}
593
594void
595rb_define_variable(const char *name, VALUE *var)
596{
597 rb_define_hooked_variable(name, var, 0, 0);
598}
599
600void
601rb_define_readonly_variable(const char *name, const VALUE *var)
602{
604}
605
606void
608 const char *name,
609 rb_gvar_getter_t *getter,
610 rb_gvar_setter_t *setter)
611{
612 if (!getter) getter = rb_gvar_val_getter;
613 if (!setter) setter = rb_gvar_readonly_setter;
614 rb_define_hooked_variable(name, 0, getter, setter);
615}
616
617static void
618rb_trace_eval(VALUE cmd, VALUE val)
619{
621}
622
623VALUE
624rb_f_trace_var(int argc, const VALUE *argv)
625{
626 VALUE var, cmd;
627 struct rb_global_entry *entry;
628 struct trace_var *trace;
629
630 if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
631 cmd = rb_block_proc();
632 }
633 if (NIL_P(cmd)) {
634 return rb_f_untrace_var(argc, argv);
635 }
636 entry = rb_global_entry(rb_to_id(var));
637 trace = ALLOC(struct trace_var);
638 trace->next = entry->var->trace;
639 trace->func = rb_trace_eval;
640 trace->data = cmd;
641 trace->removed = 0;
642 entry->var->trace = trace;
643
644 return Qnil;
645}
646
647static void
648remove_trace(struct rb_global_variable *var)
649{
650 struct trace_var *trace = var->trace;
651 struct trace_var t;
652 struct trace_var *next;
653
654 t.next = trace;
655 trace = &t;
656 while (trace->next) {
657 next = trace->next;
658 if (next->removed) {
659 trace->next = next->next;
660 xfree(next);
661 }
662 else {
663 trace = next;
664 }
665 }
666 var->trace = t.next;
667}
668
669VALUE
670rb_f_untrace_var(int argc, const VALUE *argv)
671{
672 VALUE var, cmd;
673 ID id;
674 struct rb_global_entry *entry;
675 struct trace_var *trace;
676
677 rb_scan_args(argc, argv, "11", &var, &cmd);
678 id = rb_check_id(&var);
679 if (!id) {
680 rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
681 }
682 if ((entry = rb_find_global_entry(id)) == NULL) {
683 rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
684 }
685
686 trace = entry->var->trace;
687 if (NIL_P(cmd)) {
688 VALUE ary = rb_ary_new();
689
690 while (trace) {
691 struct trace_var *next = trace->next;
692 rb_ary_push(ary, (VALUE)trace->data);
693 trace->removed = 1;
694 trace = next;
695 }
696
697 if (!entry->var->block_trace) remove_trace(entry->var);
698 return ary;
699 }
700 else {
701 while (trace) {
702 if (trace->data == cmd) {
703 trace->removed = 1;
704 if (!entry->var->block_trace) remove_trace(entry->var);
705 return rb_ary_new3(1, cmd);
706 }
707 trace = trace->next;
708 }
709 }
710 return Qnil;
711}
712
714 struct trace_var *trace;
715 VALUE val;
716};
717
718static VALUE
719trace_ev(VALUE v)
720{
721 struct trace_data *data = (void *)v;
722 struct trace_var *trace = data->trace;
723
724 while (trace) {
725 (*trace->func)(trace->data, data->val);
726 trace = trace->next;
727 }
728
729 return Qnil;
730}
731
732static VALUE
733trace_en(VALUE v)
734{
735 struct rb_global_variable *var = (void *)v;
736 var->block_trace = 0;
737 remove_trace(var);
738 return Qnil; /* not reached */
739}
740
741static VALUE
742rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val)
743{
744 struct trace_data trace;
745 struct rb_global_variable *var = entry->var;
746
747 (*var->setter)(val, entry->id, var->data);
748
749 if (var->trace && !var->block_trace) {
750 var->block_trace = 1;
751 trace.trace = var->trace;
752 trace.val = val;
753 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
754 }
755 return val;
756}
757
758VALUE
759rb_gvar_set(ID id, VALUE val)
760{
761 struct rb_global_entry *entry;
762 entry = rb_global_entry(id);
763
764 return rb_gvar_set_entry(entry, val);
765}
766
767VALUE
768rb_gv_set(const char *name, VALUE val)
769{
770 return rb_gvar_set(global_id(name), val);
771}
772
773VALUE
774rb_gvar_get(ID id)
775{
776 struct rb_global_entry *entry = rb_global_entry(id);
777 struct rb_global_variable *var = entry->var;
778 return (*var->getter)(entry->id, var->data);
779}
780
781VALUE
782rb_gv_get(const char *name)
783{
784 ID id = find_global_id(name);
785
786 if (!id) {
787 rb_warning("global variable `%s' not initialized", name);
788 return Qnil;
789 }
790
791 return rb_gvar_get(id);
792}
793
794MJIT_FUNC_EXPORTED VALUE
795rb_gvar_defined(ID id)
796{
797 struct rb_global_entry *entry = rb_global_entry(id);
798 return RBOOL(entry->var->getter != rb_gvar_undef_getter);
799}
800
802rb_gvar_getter_function_of(ID id)
803{
804 const struct rb_global_entry *entry = rb_global_entry(id);
805 return entry->var->getter;
806}
807
809rb_gvar_setter_function_of(ID id)
810{
811 const struct rb_global_entry *entry = rb_global_entry(id);
812 return entry->var->setter;
813}
814
815static enum rb_id_table_iterator_result
816gvar_i(ID key, VALUE val, void *a)
817{
818 VALUE ary = (VALUE)a;
819 rb_ary_push(ary, ID2SYM(key));
820 return ID_TABLE_CONTINUE;
821}
822
823VALUE
825{
826 VALUE ary = rb_ary_new();
827 VALUE sym, backref = rb_backref_get();
828
829 if (!rb_ractor_main_p()) {
830 rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
831 }
832
833 rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary);
834 if (!NIL_P(backref)) {
835 char buf[2];
836 int i, nmatch = rb_match_count(backref);
837 buf[0] = '$';
838 for (i = 1; i <= nmatch; ++i) {
839 if (!rb_match_nth_defined(i, backref)) continue;
840 if (i < 10) {
841 /* probably reused, make static ID */
842 buf[1] = (char)(i + '0');
843 sym = ID2SYM(rb_intern2(buf, 2));
844 }
845 else {
846 /* dynamic symbol */
847 sym = rb_str_intern(rb_sprintf("$%d", i));
848 }
849 rb_ary_push(ary, sym);
850 }
851 }
852 return ary;
853}
854
855void
857{
858 struct rb_global_entry *entry1, *entry2;
859 VALUE data1;
860 struct rb_id_table *gtbl = rb_global_tbl;
861
862 if (!rb_ractor_main_p()) {
863 rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
864 }
865
866 entry2 = rb_global_entry(name2);
867 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
868 entry1 = ALLOC(struct rb_global_entry);
869 entry1->id = name1;
870 rb_id_table_insert(gtbl, name1, (VALUE)entry1);
871 }
872 else if ((entry1 = (struct rb_global_entry *)data1)->var != entry2->var) {
873 struct rb_global_variable *var = entry1->var;
874 if (var->block_trace) {
875 rb_raise(rb_eRuntimeError, "can't alias in tracer");
876 }
877 var->counter--;
878 if (var->counter == 0) {
879 struct trace_var *trace = var->trace;
880 while (trace) {
881 struct trace_var *next = trace->next;
882 xfree(trace);
883 trace = next;
884 }
885 xfree(var);
886 }
887 }
888 else {
889 return;
890 }
891 entry2->var->counter++;
892 entry1->var = entry2->var;
893}
894
895static void
896IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
897{
898 if (UNLIKELY(!rb_ractor_main_p())) {
899 if (rb_is_instance_id(id)) { // check only normal ivars
900 rb_raise(rb_eRactorIsolationError, "can not set instance variables of classes/modules by non-main Ractors");
901 }
902 }
903}
904
905#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
906 if (UNLIKELY(!rb_ractor_main_p())) { \
907 rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
908 }
909
910static inline struct st_table *
911generic_ivtbl(VALUE obj, ID id, bool force_check_ractor)
912{
913 ASSERT_vm_locking();
914
915 if ((force_check_ractor || LIKELY(rb_is_instance_id(id)) /* not internal ID */ ) &&
916 !RB_OBJ_FROZEN_RAW(obj) &&
917 UNLIKELY(!rb_ractor_main_p()) &&
918 UNLIKELY(rb_ractor_shareable_p(obj))) {
919
920 rb_raise(rb_eRactorIsolationError, "can not access instance variables of shareable objects from non-main Ractors");
921 }
922 return generic_iv_tbl_;
923}
924
925static inline struct st_table *
926generic_ivtbl_no_ractor_check(VALUE obj)
927{
928 return generic_ivtbl(obj, 0, false);
929}
930
931static int
932gen_ivtbl_get_unlocked(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
933{
934 st_data_t data;
935
936 if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) {
937 *ivtbl = (struct gen_ivtbl *)data;
938 return 1;
939 }
940
941 return 0;
942}
943
944MJIT_FUNC_EXPORTED int
945rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
946{
947 RUBY_ASSERT(!RB_TYPE_P(obj, T_ICLASS));
948
949 st_data_t data;
950 int r = 0;
951
952 RB_VM_LOCK_ENTER();
953 {
954 if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) {
955 *ivtbl = (struct gen_ivtbl *)data;
956 r = 1;
957 }
958 }
959 RB_VM_LOCK_LEAVE();
960
961 return r;
962}
963
964MJIT_FUNC_EXPORTED int
965rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl)
966{
967 return rb_gen_ivtbl_get(obj, 0, ivtbl);
968}
969
970static size_t
971gen_ivtbl_bytes(size_t n)
972{
973 return offsetof(struct gen_ivtbl, ivptr) + n * sizeof(VALUE);
974}
975
976static struct gen_ivtbl *
977gen_ivtbl_resize(struct gen_ivtbl *old, uint32_t n)
978{
979 RUBY_ASSERT(n > 0);
980
981 uint32_t len = old ? old->numiv : 0;
982 struct gen_ivtbl *ivtbl = xrealloc(old, gen_ivtbl_bytes(n));
983
984 ivtbl->numiv = n;
985 for (; len < n; len++) {
986 ivtbl->ivptr[len] = Qundef;
987 }
988
989 return ivtbl;
990}
991
992#if 0
993static struct gen_ivtbl *
994gen_ivtbl_dup(const struct gen_ivtbl *orig)
995{
996 size_t s = gen_ivtbl_bytes(orig->numiv);
997 struct gen_ivtbl *ivtbl = xmalloc(s);
998
999 memcpy(ivtbl, orig, s);
1000
1001 return ivtbl;
1002}
1003#endif
1004
1005static int
1006generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
1007{
1008 ASSERT_vm_locking();
1009
1010 struct ivar_update *ivup = (struct ivar_update *)u;
1011 struct gen_ivtbl *ivtbl = 0;
1012
1013 if (existing) {
1014 ivtbl = (struct gen_ivtbl *)*v;
1015 if (ivup->iv_index < ivtbl->numiv) {
1016 ivup->ivtbl = ivtbl;
1017 return ST_STOP;
1018 }
1019 }
1020 FL_SET((VALUE)*k, FL_EXIVAR);
1021 ivtbl = gen_ivtbl_resize(ivtbl, ivup->shape->next_iv_index);
1022 // Reinsert in to the hash table because ivtbl might be a newly resized chunk of memory
1023 *v = (st_data_t)ivtbl;
1024 ivup->ivtbl = ivtbl;
1025#if !SHAPE_IN_BASIC_FLAGS
1026 ivtbl->shape_id = rb_shape_id(ivup->shape);
1027#endif
1028 return ST_CONTINUE;
1029}
1030
1031static void
1032gen_ivtbl_mark(const struct gen_ivtbl *ivtbl)
1033{
1034 uint32_t i;
1035
1036 for (i = 0; i < ivtbl->numiv; i++) {
1037 rb_gc_mark(ivtbl->ivptr[i]);
1038 }
1039}
1040
1041void
1042rb_mark_generic_ivar(VALUE obj)
1043{
1044 struct gen_ivtbl *ivtbl;
1045
1046 if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
1047 gen_ivtbl_mark(ivtbl);
1048 }
1049}
1050
1051void
1052rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
1053{
1054 st_data_t key = (st_data_t)rsrc;
1055 st_data_t ivtbl;
1056
1057 if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl))
1058 st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl);
1059}
1060
1061void
1063{
1064 st_data_t key = (st_data_t)obj, ivtbl;
1065
1066 if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, &ivtbl))
1067 xfree((struct gen_ivtbl *)ivtbl);
1068}
1069
1070RUBY_FUNC_EXPORTED size_t
1071rb_generic_ivar_memsize(VALUE obj)
1072{
1073 struct gen_ivtbl *ivtbl;
1074
1075 if (rb_gen_ivtbl_get(obj, 0, &ivtbl))
1076 return gen_ivtbl_bytes(ivtbl->numiv);
1077 return 0;
1078}
1079
1080#if !SHAPE_IN_BASIC_FLAGS
1081MJIT_FUNC_EXPORTED shape_id_t
1082rb_generic_shape_id(VALUE obj)
1083{
1084 struct gen_ivtbl *ivtbl = 0;
1085 shape_id_t shape_id = 0;
1086
1087 RB_VM_LOCK_ENTER();
1088 {
1089 st_table* global_iv_table = generic_ivtbl(obj, 0, false);
1090
1091 if (global_iv_table && st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
1092 shape_id = ivtbl->shape_id;
1093 }
1094 else if (OBJ_FROZEN(obj)) {
1095 shape_id = SPECIAL_CONST_SHAPE_ID;
1096 }
1097 }
1098 RB_VM_LOCK_LEAVE();
1099
1100 return shape_id;
1101}
1102#endif
1103
1104static size_t
1105gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
1106{
1107 uint32_t i;
1108 size_t n = 0;
1109
1110 for (i = 0; i < ivtbl->numiv; i++) {
1111 if (!UNDEF_P(ivtbl->ivptr[i])) {
1112 n++;
1113 }
1114 }
1115
1116 return n;
1117}
1118
1119VALUE
1120rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
1121{
1122 if (SPECIAL_CONST_P(obj)) return undef;
1123
1124 shape_id_t shape_id;
1125 VALUE * ivar_list;
1126 rb_shape_t * shape;
1127
1128#if SHAPE_IN_BASIC_FLAGS
1129 shape_id = RBASIC_SHAPE_ID(obj);
1130#endif
1131
1132 switch (BUILTIN_TYPE(obj)) {
1133 case T_CLASS:
1134 case T_MODULE:
1135 {
1136 bool found;
1137 VALUE val;
1138
1139 RB_VM_LOCK_ENTER();
1140 {
1141#if !SHAPE_IN_BASIC_FLAGS
1142 shape_id = RCLASS_SHAPE_ID(obj);
1143#endif
1144
1145 attr_index_t index = 0;
1146 shape = rb_shape_get_shape_by_id(shape_id);
1147 found = rb_shape_get_iv_index(shape, id, &index);
1148
1149 if (found) {
1150 ivar_list = RCLASS_IVPTR(obj);
1151 RUBY_ASSERT(ivar_list);
1152
1153 val = ivar_list[index];
1154 }
1155 else {
1156 val = undef;
1157 }
1158 }
1159 RB_VM_LOCK_LEAVE();
1160
1161 if (found &&
1162 rb_is_instance_id(id) &&
1163 UNLIKELY(!rb_ractor_main_p()) &&
1164 !rb_ractor_shareable_p(val)) {
1165 rb_raise(rb_eRactorIsolationError,
1166 "can not get unshareable values from instance variables of classes/modules from non-main Ractors");
1167 }
1168 return val;
1169 }
1170 case T_OBJECT:
1171 {
1172#if !SHAPE_IN_BASIC_FLAGS
1173 shape_id = ROBJECT_SHAPE_ID(obj);
1174#endif
1175 if (rb_shape_obj_too_complex(obj)) {
1176 struct rb_id_table * iv_table = ROBJECT_IV_HASH(obj);
1177 VALUE val;
1178 if (rb_id_table_lookup(iv_table, id, &val)) {
1179 return val;
1180 }
1181 else {
1182 return undef;
1183 }
1184 }
1185
1186 RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
1187 ivar_list = ROBJECT_IVPTR(obj);
1188 break;
1189 }
1190 default:
1191 if (FL_TEST_RAW(obj, FL_EXIVAR)) {
1192 struct gen_ivtbl *ivtbl;
1193 rb_gen_ivtbl_get(obj, id, &ivtbl);
1194#if !SHAPE_IN_BASIC_FLAGS
1195 shape_id = ivtbl->shape_id;
1196#endif
1197 ivar_list = ivtbl->ivptr;
1198 }
1199 else {
1200 return undef;
1201 }
1202 break;
1203 }
1204
1205 attr_index_t index = 0;
1206 shape = rb_shape_get_shape_by_id(shape_id);
1207 if (rb_shape_get_iv_index(shape, id, &index)) {
1208 return ivar_list[index];
1209 }
1210
1211 return undef;
1212}
1213
1214VALUE
1216{
1217 VALUE iv = rb_ivar_lookup(obj, id, Qnil);
1218 RB_DEBUG_COUNTER_INC(ivar_get_base);
1219 return iv;
1220}
1221
1222VALUE
1224{
1225 return rb_ivar_lookup(obj, id, Qnil);
1226}
1227
1228static VALUE
1229rb_ivar_delete(VALUE obj, ID id, VALUE undef)
1230{
1231 rb_check_frozen(obj);
1232
1233 VALUE val = undef;
1234 rb_shape_t * shape = rb_shape_get_shape(obj);
1235
1236 switch (BUILTIN_TYPE(obj)) {
1237 case T_CLASS:
1238 case T_MODULE:
1239 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1240
1241 RB_VM_LOCK_ENTER();
1242 {
1243 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1244 }
1245 RB_VM_LOCK_LEAVE();
1246
1247 break;
1248 case T_OBJECT: {
1249 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1250
1251 break;
1252 }
1253 default: {
1254 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1255
1256 break;
1257 }
1258 }
1259
1260 return val;
1261}
1262
1263VALUE
1264rb_attr_delete(VALUE obj, ID id)
1265{
1266 return rb_ivar_delete(obj, id, Qnil);
1267}
1268
1269static void
1270generic_ivar_set(VALUE obj, ID id, VALUE val)
1271{
1272 struct ivar_update ivup;
1273
1274 attr_index_t index;
1275 // The returned shape will have `id` in its iv_table
1276 rb_shape_t *shape = rb_shape_get_shape(obj);
1277 bool found = rb_shape_get_iv_index(shape, id, &index);
1278 if (!found) {
1279 index = shape->next_iv_index;
1280 shape = rb_shape_get_next(shape, obj, id);
1281 RUBY_ASSERT(index == (shape->next_iv_index - 1));
1282 }
1283
1284 ivup.shape = shape;
1285
1286 RB_VM_LOCK_ENTER();
1287 {
1288 ivup.iv_index = (uint32_t)index;
1289
1290 st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update, (st_data_t)&ivup);
1291 }
1292 RB_VM_LOCK_LEAVE();
1293
1294 ivup.ivtbl->ivptr[ivup.iv_index] = val;
1295 RB_OBJ_WRITTEN(obj, Qundef, val);
1296
1297 if (!found) {
1298 rb_shape_set_shape(obj, shape);
1299 }
1300}
1301
1302static VALUE *
1303obj_ivar_heap_alloc(VALUE obj, size_t newsize)
1304{
1305 VALUE *newptr = rb_transient_heap_alloc(obj, sizeof(VALUE) * newsize);
1306
1307 if (newptr != NULL) {
1308 ROBJ_TRANSIENT_SET(obj);
1309 }
1310 else {
1311 ROBJ_TRANSIENT_UNSET(obj);
1312 newptr = ALLOC_N(VALUE, newsize);
1313 }
1314 return newptr;
1315}
1316
1317static VALUE *
1318obj_ivar_heap_realloc(VALUE obj, int32_t len, size_t newsize)
1319{
1320 VALUE *newptr;
1321 int i;
1322
1323 if (ROBJ_TRANSIENT_P(obj)) {
1324 const VALUE *orig_ptr = ROBJECT(obj)->as.heap.ivptr;
1325 newptr = obj_ivar_heap_alloc(obj, newsize);
1326
1327 assert(newptr);
1328 ROBJECT(obj)->as.heap.ivptr = newptr;
1329 for (i=0; i<(int)len; i++) {
1330 newptr[i] = orig_ptr[i];
1331 }
1332 }
1333 else {
1334 REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize);
1335 newptr = ROBJECT(obj)->as.heap.ivptr;
1336 }
1337
1338 return newptr;
1339}
1340
1341#if USE_TRANSIENT_HEAP
1342void
1343rb_obj_transient_heap_evacuate(VALUE obj, int promote)
1344{
1345 if (ROBJ_TRANSIENT_P(obj)) {
1346 assert(!RB_FL_TEST_RAW(obj, ROBJECT_EMBED));
1347
1348 uint32_t len = ROBJECT_IV_CAPACITY(obj);
1349 RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
1350 const VALUE *old_ptr = ROBJECT_IVPTR(obj);
1351 VALUE *new_ptr;
1352
1353 if (promote) {
1354 new_ptr = ALLOC_N(VALUE, len);
1355 ROBJ_TRANSIENT_UNSET(obj);
1356 }
1357 else {
1358 new_ptr = obj_ivar_heap_alloc(obj, len);
1359 }
1360 MEMCPY(new_ptr, old_ptr, VALUE, len);
1361 ROBJECT(obj)->as.heap.ivptr = new_ptr;
1362 }
1363}
1364#endif
1365
1366void
1367rb_ensure_iv_list_size(VALUE obj, uint32_t current_capacity, uint32_t new_capacity)
1368{
1369 RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
1370 VALUE *ptr = ROBJECT_IVPTR(obj);
1371 VALUE *newptr;
1372
1373 if (RBASIC(obj)->flags & ROBJECT_EMBED) {
1374 newptr = obj_ivar_heap_alloc(obj, new_capacity);
1375 MEMCPY(newptr, ptr, VALUE, current_capacity);
1376 RB_FL_UNSET_RAW(obj, ROBJECT_EMBED);
1377 ROBJECT(obj)->as.heap.ivptr = newptr;
1378 }
1379 else {
1380 newptr = obj_ivar_heap_realloc(obj, current_capacity, new_capacity);
1381 }
1382}
1383
1384struct gen_ivtbl *
1385rb_ensure_generic_iv_list_size(VALUE obj, uint32_t newsize)
1386{
1387 struct gen_ivtbl * ivtbl = 0;
1388
1389 RB_VM_LOCK_ENTER();
1390 {
1391 if (UNLIKELY(!gen_ivtbl_get_unlocked(obj, 0, &ivtbl) || newsize > ivtbl->numiv)) {
1392 ivtbl = gen_ivtbl_resize(ivtbl, newsize);
1393 st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)obj, (st_data_t)ivtbl);
1394 FL_SET_RAW(obj, FL_EXIVAR);
1395 }
1396 }
1397 RB_VM_LOCK_LEAVE();
1398
1399 RUBY_ASSERT(ivtbl);
1400
1401 return ivtbl;
1402}
1403
1404// @note May raise when there are too many instance variables.
1405rb_shape_t *
1406rb_grow_iv_list(VALUE obj)
1407{
1408 rb_shape_t * initial_shape = rb_shape_get_shape(obj);
1409 uint32_t len = initial_shape->capacity;
1410 RUBY_ASSERT(len > 0);
1411 uint32_t newsize = (uint32_t)(len * 2);
1412
1413 rb_shape_t * res = rb_shape_transition_shape_capa(initial_shape, newsize);
1414
1415 rb_ensure_iv_list_size(obj, len, newsize);
1416
1417 rb_shape_set_shape(obj, res);
1418
1419 return res;
1420}
1421
1422int
1423rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg)
1424{
1425 rb_id_table_insert((struct rb_id_table *)arg, key, val);
1426 return ST_CONTINUE;
1427}
1428
1429attr_index_t
1430rb_obj_ivar_set(VALUE obj, ID id, VALUE val)
1431{
1432 attr_index_t index;
1433
1434 rb_shape_t *shape = rb_shape_get_shape(obj);
1435 uint32_t num_iv = shape->capacity;
1436
1437 if (rb_shape_obj_too_complex(obj)) {
1438 struct rb_id_table * table = ROBJECT_IV_HASH(obj);
1439 rb_id_table_insert(table, id, val);
1440 RB_OBJ_WRITTEN(obj, Qundef, val);
1441 return 0;
1442 }
1443
1444 if (!rb_shape_get_iv_index(shape, id, &index)) {
1445 index = shape->next_iv_index;
1446 if (index >= MAX_IVARS) {
1447 rb_raise(rb_eArgError, "too many instance variables");
1448 }
1449
1450 RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
1451
1452 if (UNLIKELY(shape->next_iv_index >= num_iv)) {
1453 RUBY_ASSERT(shape->next_iv_index == num_iv);
1454
1455 shape = rb_grow_iv_list(obj);
1456 RUBY_ASSERT(shape->type == SHAPE_CAPACITY_CHANGE);
1457 }
1458
1459 rb_shape_t *next_shape = rb_shape_get_next(shape, obj, id);
1460
1461 if (next_shape->type == SHAPE_OBJ_TOO_COMPLEX) {
1462 struct rb_id_table * table = rb_id_table_create(shape->next_iv_index);
1463
1464 // Evacuate all previous values from shape into id_table
1465 rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table);
1466
1467 // Insert new value too
1468 rb_id_table_insert(table, id, val);
1469 RB_OBJ_WRITTEN(obj, Qundef, val);
1470
1471 rb_shape_set_too_complex(obj);
1472 RUBY_ASSERT(rb_shape_obj_too_complex(obj));
1473
1474 if (ROBJ_TRANSIENT_P(obj)) {
1475 ROBJ_TRANSIENT_UNSET(obj);
1476 }
1477 else if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) {
1478 xfree(ROBJECT(obj)->as.heap.ivptr);
1479 }
1480
1481 ROBJECT(obj)->as.heap.ivptr = (VALUE *)table;
1482
1483 return 0;
1484 }
1485 else {
1486 rb_shape_set_shape(obj, next_shape);
1487 RUBY_ASSERT(next_shape->type == SHAPE_IVAR);
1488 RUBY_ASSERT(index == (next_shape->next_iv_index - 1));
1489 }
1490 }
1491
1492 RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
1493 RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[index], val);
1494
1495 return index;
1496}
1497
1498/* Set the instance variable +val+ on object +obj+ at ivar name +id+.
1499 * This function only works with T_OBJECT objects, so make sure
1500 * +obj+ is of type T_OBJECT before using this function.
1501 */
1502VALUE
1503rb_vm_set_ivar_id(VALUE obj, ID id, VALUE val)
1504{
1506 rb_obj_ivar_set(obj, id, val);
1507 return val;
1508}
1509
1510bool
1511rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id)
1512{
1513 if (rb_shape_get_shape_id(obj) == shape_id) {
1514 return false;
1515 }
1516
1517#if SHAPE_IN_BASIC_FLAGS
1518 RBASIC_SET_SHAPE_ID(obj, shape_id);
1519#else
1520 switch (BUILTIN_TYPE(obj)) {
1521 case T_OBJECT:
1522 ROBJECT_SET_SHAPE_ID(obj, shape_id);
1523 break;
1524 case T_CLASS:
1525 case T_MODULE:
1526 RCLASS_EXT(obj)->shape_id = shape_id;
1527 break;
1528 default:
1529 if (shape_id != SPECIAL_CONST_SHAPE_ID) {
1530 struct gen_ivtbl *ivtbl = 0;
1531 RB_VM_LOCK_ENTER();
1532 {
1533 st_table* global_iv_table = generic_ivtbl(obj, 0, false);
1534
1535 if (st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
1536 ivtbl->shape_id = shape_id;
1537 }
1538 else {
1539 rb_bug("Expected shape_id entry in global iv table");
1540 }
1541 }
1542 RB_VM_LOCK_LEAVE();
1543 }
1544 }
1545#endif
1546
1547 return true;
1548}
1549
1557{
1558 if (RB_FL_ABLE(x)) {
1559 RB_OBJ_FREEZE_RAW(x);
1560
1561 rb_shape_transition_shape_frozen(x);
1562
1563 if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
1565 }
1566 }
1567}
1568
1569static void
1570ivar_set(VALUE obj, ID id, VALUE val)
1571{
1572 RB_DEBUG_COUNTER_INC(ivar_set_base);
1573
1574 switch (BUILTIN_TYPE(obj)) {
1575 case T_OBJECT:
1576 {
1577 rb_obj_ivar_set(obj, id, val);
1578 break;
1579 }
1580 case T_CLASS:
1581 case T_MODULE:
1582 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1583 rb_class_ivar_set(obj, id, val);
1584
1585 break;
1586 default:
1587 generic_ivar_set(obj, id, val);
1588 break;
1589 }
1590}
1591
1592VALUE
1594{
1595 rb_check_frozen(obj);
1596 ivar_set(obj, id, val);
1597 return val;
1598}
1599
1600void
1601rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
1602{
1603 // should be internal instance variable name (no @ prefix)
1604 VM_ASSERT(!rb_is_instance_id(id));
1605
1606 ivar_set(obj, id, val);
1607}
1608
1609VALUE
1611{
1612 attr_index_t index;
1613
1614 if (SPECIAL_CONST_P(obj)) return Qfalse;
1615 if (rb_shape_obj_too_complex(obj)) {
1616 VALUE idx;
1617 if (!rb_id_table_lookup(ROBJECT_IV_HASH(obj), id, &idx)) {
1618 return Qfalse;
1619 }
1620
1621 return Qtrue;
1622 }
1623 else {
1624 return RBOOL(rb_shape_get_iv_index(rb_shape_get_shape(obj), id, &index));
1625 }
1626}
1627
1628typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
1629st_data_t rb_st_nth_key(st_table *tab, st_index_t index);
1630
1632 VALUE obj;
1633 struct gen_ivtbl * ivtbl;
1634 st_data_t arg;
1635 rb_ivar_foreach_callback_func *func;
1636};
1637
1638static void
1639iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_func *callback, struct iv_itr_data * itr_data)
1640{
1641 switch ((enum shape_type)shape->type) {
1642 case SHAPE_ROOT:
1643 return;
1644 case SHAPE_IVAR:
1645 iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
1646 VALUE * iv_list;
1647 switch (BUILTIN_TYPE(itr_data->obj)) {
1648 case T_OBJECT:
1649 RUBY_ASSERT(!rb_shape_obj_too_complex(itr_data->obj));
1650 iv_list = ROBJECT_IVPTR(itr_data->obj);
1651 break;
1652 case T_CLASS:
1653 case T_MODULE:
1654 iv_list = RCLASS_IVPTR(itr_data->obj);
1655 break;
1656 default:
1657 iv_list = itr_data->ivtbl->ivptr;
1658 break;
1659 }
1660 VALUE val = iv_list[shape->next_iv_index - 1];
1661 if (!UNDEF_P(val)) {
1662 callback(shape->edge_name, val, itr_data->arg);
1663 }
1664 return;
1665 case SHAPE_INITIAL_CAPACITY:
1666 case SHAPE_CAPACITY_CHANGE:
1667 case SHAPE_FROZEN:
1668 case SHAPE_T_OBJECT:
1669 iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
1670 return;
1671 case SHAPE_OBJ_TOO_COMPLEX:
1672 rb_bug("Unreachable\n");
1673 }
1674}
1675
1676static enum rb_id_table_iterator_result
1677each_hash_iv(ID id, VALUE val, void *data)
1678{
1679 struct iv_itr_data * itr_data = (struct iv_itr_data *)data;
1680 rb_ivar_foreach_callback_func *callback = itr_data->func;
1681 return callback(id, val, itr_data->arg);
1682}
1683
1684static void
1685obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1686{
1687 rb_shape_t* shape = rb_shape_get_shape(obj);
1688 struct iv_itr_data itr_data;
1689 itr_data.obj = obj;
1690 itr_data.arg = arg;
1691 itr_data.func = func;
1692 if (rb_shape_obj_too_complex(obj)) {
1693 rb_id_table_foreach(ROBJECT_IV_HASH(obj), each_hash_iv, &itr_data);
1694 }
1695 else {
1696 iterate_over_shapes_with_callback(shape, func, &itr_data);
1697 }
1698}
1699
1700static void
1701gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1702{
1703 rb_shape_t *shape = rb_shape_get_shape(obj);
1704 struct gen_ivtbl *ivtbl;
1705 if (!rb_gen_ivtbl_get(obj, 0, &ivtbl)) return;
1706
1707 struct iv_itr_data itr_data;
1708 itr_data.obj = obj;
1709 itr_data.ivtbl = ivtbl;
1710 itr_data.arg = arg;
1711 iterate_over_shapes_with_callback(shape, func, &itr_data);
1712}
1713
1714static void
1715class_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1716{
1717 RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
1718
1719 rb_shape_t* shape = rb_shape_get_shape(obj);
1720 struct iv_itr_data itr_data;
1721 itr_data.obj = obj;
1722 itr_data.arg = arg;
1723 iterate_over_shapes_with_callback(shape, func, &itr_data);
1724}
1725
1726void
1728{
1729 struct gen_ivtbl *obj_ivtbl;
1730 struct gen_ivtbl *new_ivtbl;
1731
1732 rb_check_frozen(clone);
1733
1734 if (!FL_TEST(obj, FL_EXIVAR)) {
1735 goto clear;
1736 }
1737
1738 if (rb_gen_ivtbl_get(obj, 0, &obj_ivtbl)) {
1739 if (gen_ivtbl_count(obj_ivtbl) == 0)
1740 goto clear;
1741
1742 new_ivtbl = gen_ivtbl_resize(0, obj_ivtbl->numiv);
1743 FL_SET(clone, FL_EXIVAR);
1744
1745 for (uint32_t i=0; i<obj_ivtbl->numiv; i++) {
1746 new_ivtbl->ivptr[i] = obj_ivtbl->ivptr[i];
1747 RB_OBJ_WRITTEN(clone, Qundef, &new_ivtbl[i]);
1748 }
1749
1750 /*
1751 * c.ivtbl may change in gen_ivar_copy due to realloc,
1752 * no need to free
1753 */
1754 RB_VM_LOCK_ENTER();
1755 {
1756 generic_ivtbl_no_ractor_check(clone);
1757 st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)new_ivtbl);
1758 }
1759 RB_VM_LOCK_LEAVE();
1760
1761 rb_shape_t * obj_shape = rb_shape_get_shape(obj);
1762 if (rb_shape_frozen_shape_p(obj_shape)) {
1763 rb_shape_set_shape_id(clone, obj_shape->parent_id);
1764 }
1765 else {
1766 rb_shape_set_shape(clone, obj_shape);
1767 }
1768 }
1769 return;
1770
1771 clear:
1772 if (FL_TEST(clone, FL_EXIVAR)) {
1773 rb_free_generic_ivar(clone);
1774 FL_UNSET(clone, FL_EXIVAR);
1775 }
1776}
1777
1778void
1779rb_replace_generic_ivar(VALUE clone, VALUE obj)
1780{
1782
1783 RB_VM_LOCK_ENTER();
1784 {
1785 st_data_t ivtbl, obj_data = (st_data_t)obj;
1786 if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) {
1787 st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl);
1788 st_delete(generic_iv_tbl_, &obj_data, NULL);
1789 }
1790 else {
1791 rb_bug("unreachable");
1792 }
1793 }
1794 RB_VM_LOCK_LEAVE();
1795
1796 FL_SET(clone, FL_EXIVAR);
1797}
1798
1799void
1800rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1801{
1802 if (SPECIAL_CONST_P(obj)) return;
1803 switch (BUILTIN_TYPE(obj)) {
1804 case T_OBJECT:
1805 obj_ivar_each(obj, func, arg);
1806 break;
1807 case T_CLASS:
1808 case T_MODULE:
1809 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
1810 RB_VM_LOCK_ENTER();
1811 {
1812 class_ivar_each(obj, func, arg);
1813 }
1814 RB_VM_LOCK_LEAVE();
1815 break;
1816 default:
1817 if (FL_TEST(obj, FL_EXIVAR)) {
1818 gen_ivar_each(obj, func, arg);
1819 }
1820 break;
1821 }
1822}
1823
1824st_index_t
1826{
1827 if (SPECIAL_CONST_P(obj)) return 0;
1828
1829 switch (BUILTIN_TYPE(obj)) {
1830 case T_OBJECT:
1831 if (rb_shape_obj_too_complex(obj)) {
1832 return ROBJECT_IV_COUNT(obj);
1833 }
1834
1835 if (rb_shape_get_shape(obj)->next_iv_index > 0) {
1836 st_index_t i, count, num = ROBJECT_IV_COUNT(obj);
1837 const VALUE *const ivptr = ROBJECT_IVPTR(obj);
1838 for (i = count = 0; i < num; ++i) {
1839 if (!UNDEF_P(ivptr[i])) {
1840 count++;
1841 }
1842 }
1843 return count;
1844 }
1845 break;
1846 case T_CLASS:
1847 case T_MODULE:
1848 if (rb_shape_get_shape(obj)->next_iv_index > 0) {
1849 st_index_t count = 0;
1850
1851 RB_VM_LOCK_ENTER();
1852 {
1853 st_index_t i, num = rb_shape_get_shape(obj)->next_iv_index;
1854 const VALUE *const ivptr = RCLASS_IVPTR(obj);
1855 for (i = count = 0; i < num; ++i) {
1856 if (!UNDEF_P(ivptr[i])) {
1857 count++;
1858 }
1859 }
1860 }
1861 RB_VM_LOCK_LEAVE();
1862
1863 return count;
1864 }
1865 break;
1866 default:
1867 if (FL_TEST(obj, FL_EXIVAR)) {
1868 struct gen_ivtbl *ivtbl;
1869
1870 if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
1871 return gen_ivtbl_count(ivtbl);
1872 }
1873 }
1874 break;
1875 }
1876 return 0;
1877}
1878
1879static int
1880ivar_i(st_data_t k, st_data_t v, st_data_t a)
1881{
1882 ID key = (ID)k;
1883 VALUE ary = (VALUE)a;
1884
1885 if (rb_is_instance_id(key)) {
1886 rb_ary_push(ary, ID2SYM(key));
1887 }
1888 return ST_CONTINUE;
1889}
1890
1891/*
1892 * call-seq:
1893 * obj.instance_variables -> array
1894 *
1895 * Returns an array of instance variable names for the receiver. Note
1896 * that simply defining an accessor does not create the corresponding
1897 * instance variable.
1898 *
1899 * class Fred
1900 * attr_accessor :a1
1901 * def initialize
1902 * @iv = 3
1903 * end
1904 * end
1905 * Fred.new.instance_variables #=> [:@iv]
1906 */
1907
1908VALUE
1910{
1911 VALUE ary;
1912
1913 ary = rb_ary_new();
1914 rb_ivar_foreach(obj, ivar_i, ary);
1915 return ary;
1916}
1917
1918#define rb_is_constant_id rb_is_const_id
1919#define rb_is_constant_name rb_is_const_name
1920#define id_for_var(obj, name, part, type) \
1921 id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name")
1922#define id_for_var_message(obj, name, type, message) \
1923 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
1924static ID
1925check_id_type(VALUE obj, VALUE *pname,
1926 int (*valid_id_p)(ID), int (*valid_name_p)(VALUE),
1927 const char *message, size_t message_len)
1928{
1929 ID id = rb_check_id(pname);
1930 VALUE name = *pname;
1931
1932 if (id ? !valid_id_p(id) : !valid_name_p(name)) {
1933 rb_name_err_raise_str(rb_fstring_new(message, message_len),
1934 obj, name);
1935 }
1936 return id;
1937}
1938
1939/*
1940 * call-seq:
1941 * obj.remove_instance_variable(symbol) -> obj
1942 * obj.remove_instance_variable(string) -> obj
1943 *
1944 * Removes the named instance variable from <i>obj</i>, returning that
1945 * variable's value.
1946 * String arguments are converted to symbols.
1947 *
1948 * class Dummy
1949 * attr_reader :var
1950 * def initialize
1951 * @var = 99
1952 * end
1953 * def remove
1954 * remove_instance_variable(:@var)
1955 * end
1956 * end
1957 * d = Dummy.new
1958 * d.var #=> 99
1959 * d.remove #=> 99
1960 * d.var #=> nil
1961 */
1962
1963VALUE
1965{
1966 VALUE val = Qundef;
1967 const ID id = id_for_var(obj, name, an, instance);
1968
1969 // Frozen check comes here because it's expected that we raise a
1970 // NameError (from the id_for_var check) before we raise a FrozenError
1971 rb_check_frozen(obj);
1972
1973 if (!id) {
1974 goto not_defined;
1975 }
1976
1977 rb_shape_t * shape = rb_shape_get_shape(obj);
1978
1979 switch (BUILTIN_TYPE(obj)) {
1980 case T_CLASS:
1981 case T_MODULE:
1982 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1983 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1984 break;
1985 case T_OBJECT: {
1986 if (rb_shape_obj_too_complex(obj)) {
1987 if (rb_id_table_lookup(ROBJECT_IV_HASH(obj), id, &val)) {
1988 rb_id_table_delete(ROBJECT_IV_HASH(obj), id);
1989 }
1990 }
1991 else {
1992 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1993 }
1994 break;
1995 }
1996 default: {
1997 rb_shape_transition_shape_remove_ivar(obj, id, shape, &val);
1998 break;
1999 }
2000 }
2001
2002 if (val != Qundef) {
2003 return val;
2004 }
2005
2006 not_defined:
2007 rb_name_err_raise("instance variable %1$s not defined",
2008 obj, name);
2010}
2011
2012NORETURN(static void uninitialized_constant(VALUE, VALUE));
2013static void
2014uninitialized_constant(VALUE klass, VALUE name)
2015{
2016 if (klass && rb_class_real(klass) != rb_cObject)
2017 rb_name_err_raise("uninitialized constant %2$s::%1$s",
2018 klass, name);
2019 else
2020 rb_name_err_raise("uninitialized constant %1$s",
2021 klass, name);
2022}
2023
2024VALUE
2025rb_const_missing(VALUE klass, VALUE name)
2026{
2027 VALUE value = rb_funcallv(klass, idConst_missing, 1, &name);
2028 rb_vm_inc_const_missing_count();
2029 return value;
2030}
2031
2032
2033/*
2034 * call-seq:
2035 * mod.const_missing(sym) -> obj
2036 *
2037 * Invoked when a reference is made to an undefined constant in
2038 * <i>mod</i>. It is passed a symbol for the undefined constant, and
2039 * returns a value to be used for that constant. The
2040 * following code is an example of the same:
2041 *
2042 * def Foo.const_missing(name)
2043 * name # return the constant name as Symbol
2044 * end
2045 *
2046 * Foo::UNDEFINED_CONST #=> :UNDEFINED_CONST: symbol returned
2047 *
2048 * In the next example when a reference is made to an undefined constant,
2049 * it attempts to load a file whose name is the lowercase version of the
2050 * constant (thus class <code>Fred</code> is assumed to be in file
2051 * <code>fred.rb</code>). If found, it returns the loaded class. It
2052 * therefore implements an autoload feature similar to Kernel#autoload and
2053 * Module#autoload.
2054 *
2055 * def Object.const_missing(name)
2056 * @looked_for ||= {}
2057 * str_name = name.to_s
2058 * raise "Class not found: #{name}" if @looked_for[str_name]
2059 * @looked_for[str_name] = 1
2060 * file = str_name.downcase
2061 * require file
2062 * klass = const_get(name)
2063 * return klass if klass
2064 * raise "Class not found: #{name}"
2065 * end
2066 *
2067 */
2068
2069VALUE
2070rb_mod_const_missing(VALUE klass, VALUE name)
2071{
2072 VALUE ref = GET_EC()->private_const_reference;
2073 rb_vm_pop_cfunc_frame();
2074 if (ref) {
2075 rb_name_err_raise("private constant %2$s::%1$s referenced",
2076 ref, name);
2077 }
2078 uninitialized_constant(klass, name);
2079
2081}
2082
2083static void
2084autoload_table_mark(void *ptr)
2085{
2086 rb_mark_tbl_no_pin((st_table *)ptr);
2087}
2088
2089static void
2090autoload_table_free(void *ptr)
2091{
2092 st_free_table((st_table *)ptr);
2093}
2094
2095static size_t
2096autoload_table_memsize(const void *ptr)
2097{
2098 const st_table *tbl = ptr;
2099 return st_memsize(tbl);
2100}
2101
2102static void
2103autoload_table_compact(void *ptr)
2104{
2105 rb_gc_update_tbl_refs((st_table *)ptr);
2106}
2107
2108static const rb_data_type_t autoload_table_type = {
2109 "autoload_table",
2110 {autoload_table_mark, autoload_table_free, autoload_table_memsize, autoload_table_compact,},
2111 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2112};
2113
2114#define check_autoload_table(av) \
2115 (struct st_table *)rb_check_typeddata((av), &autoload_table_type)
2116
2117static VALUE
2118autoload_data(VALUE mod, ID id)
2119{
2120 struct st_table *tbl;
2121 st_data_t val;
2122
2123 // If we are called with a non-origin ICLASS, fetch the autoload data from
2124 // the original module.
2125 if (RB_TYPE_P(mod, T_ICLASS)) {
2126 if (FL_TEST_RAW(mod, RICLASS_IS_ORIGIN)) {
2127 return 0;
2128 }
2129 else {
2130 mod = RBASIC(mod)->klass;
2131 }
2132 }
2133
2134 RUBY_ASSERT(RB_TYPE_P(mod, T_CLASS) || RB_TYPE_P(mod, T_MODULE));
2135
2136 // Look up the instance variable table for `autoload`, then index into that table with the given constant name `id`.
2137
2138 VALUE tbl_value = rb_ivar_lookup(mod, autoload, 0);
2139 if (!tbl_value || !(tbl = check_autoload_table(tbl_value)) || !st_lookup(tbl, (st_data_t)id, &val)) {
2140 return 0;
2141 }
2142
2143 return (VALUE)val;
2144}
2145
2146// Every autoload constant has exactly one instance of autoload_const, stored in `autoload_features`. Since multiple autoload constants can refer to the same file, every `autoload_const` refers to a de-duplicated `autoload_data`.
2148 // The linked list node of all constants which are loaded by the related autoload feature.
2149 struct ccan_list_node cnode; /* <=> autoload_data.constants */
2150
2151 // The shared "autoload_data" if multiple constants are defined from the same feature.
2152 VALUE autoload_data_value;
2153
2154 // The module we are loading a constant into.
2155 VALUE module;
2156
2157 // The name of the constant we are loading.
2158 ID name;
2159
2160 // The value of the constant (after it's loaded).
2161 VALUE value;
2162
2163 // The constant entry flags which need to be re-applied after autoloading the feature.
2164 rb_const_flag_t flag;
2165
2166 // The source file and line number that defined this constant (different from feature path).
2167 VALUE file;
2168 int line;
2169};
2170
2171// Each `autoload_data` uniquely represents a specific feature which can be loaded, and a list of constants which it is able to define. We use a mutex to coordinate multiple threads trying to load the same feature.
2173 // The feature path to require to load this constant.
2174 VALUE feature;
2175
2176 // The mutex which is protecting autoloading this feature.
2177 VALUE mutex;
2178
2179 // The process fork serial number since the autoload mutex will become invalid on fork.
2180 rb_serial_t fork_gen;
2181
2182 // The linked list of all constants that are going to be loaded by this autoload.
2183 struct ccan_list_head constants; /* <=> autoload_const.cnode */
2184};
2185
2186static void
2187autoload_data_compact(void *ptr)
2188{
2189 struct autoload_data *p = ptr;
2190
2191 p->feature = rb_gc_location(p->feature);
2192 p->mutex = rb_gc_location(p->mutex);
2193}
2194
2195static void
2196autoload_data_mark(void *ptr)
2197{
2198 struct autoload_data *p = ptr;
2199
2200 rb_gc_mark_movable(p->feature);
2201 rb_gc_mark_movable(p->mutex);
2202}
2203
2204static void
2205autoload_data_free(void *ptr)
2206{
2207 struct autoload_data *p = ptr;
2208
2209 // We may leak some memory at VM shutdown time, no big deal...?
2210 if (ccan_list_empty(&p->constants)) {
2211 ruby_xfree(p);
2212 }
2213}
2214
2215static size_t
2216autoload_data_memsize(const void *ptr)
2217{
2218 return sizeof(struct autoload_data);
2219}
2220
2221static const rb_data_type_t autoload_data_type = {
2222 "autoload_data",
2223 {autoload_data_mark, autoload_data_free, autoload_data_memsize, autoload_data_compact},
2224 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2225};
2226
2227static void
2228autoload_const_compact(void *ptr)
2229{
2230 struct autoload_const *ac = ptr;
2231
2232 ac->module = rb_gc_location(ac->module);
2233 ac->autoload_data_value = rb_gc_location(ac->autoload_data_value);
2234 ac->value = rb_gc_location(ac->value);
2235 ac->file = rb_gc_location(ac->file);
2236}
2237
2238static void
2239autoload_const_mark(void *ptr)
2240{
2241 struct autoload_const *ac = ptr;
2242
2243 rb_gc_mark_movable(ac->module);
2244 rb_gc_mark_movable(ac->autoload_data_value);
2245 rb_gc_mark_movable(ac->value);
2246 rb_gc_mark_movable(ac->file);
2247}
2248
2249static size_t
2250autoload_const_memsize(const void *ptr)
2251{
2252 return sizeof(struct autoload_const);
2253}
2254
2255static void
2256autoload_const_free(void *ptr)
2257{
2258 struct autoload_const *autoload_const = ptr;
2259
2260 ccan_list_del(&autoload_const->cnode);
2261 ruby_xfree(ptr);
2262}
2263
2264static const rb_data_type_t autoload_const_type = {
2265 "autoload_const",
2266 {autoload_const_mark, autoload_const_free, autoload_const_memsize, autoload_const_compact,},
2267 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2268};
2269
2270static struct autoload_data *
2271get_autoload_data(VALUE autoload_const_value, struct autoload_const **autoload_const_pointer)
2272{
2273 struct autoload_const *autoload_const = rb_check_typeddata(autoload_const_value, &autoload_const_type);
2274
2275 struct autoload_data *autoload_data = rb_check_typeddata(autoload_const->autoload_data_value, &autoload_data_type);
2276
2277 /* do not reach across stack for ->state after forking: */
2278 if (autoload_data && autoload_data->fork_gen != GET_VM()->fork_gen) {
2279 autoload_data->mutex = Qnil;
2280 autoload_data->fork_gen = 0;
2281 }
2282
2283 if (autoload_const_pointer) *autoload_const_pointer = autoload_const;
2284
2285 return autoload_data;
2286}
2287
2288RUBY_FUNC_EXPORTED void
2289rb_autoload(VALUE module, ID name, const char *feature)
2290{
2291 if (!feature || !*feature) {
2292 rb_raise(rb_eArgError, "empty feature name");
2293 }
2294
2295 rb_autoload_str(module, name, rb_fstring_cstr(feature));
2296}
2297
2298static void const_set(VALUE klass, ID id, VALUE val);
2299static void const_added(VALUE klass, ID const_name);
2300
2302 VALUE module;
2303 ID name;
2304 VALUE feature;
2305};
2306
2307static VALUE
2308autoload_feature_lookup_or_create(VALUE feature, struct autoload_data **autoload_data_pointer)
2309{
2310 RUBY_ASSERT_MUTEX_OWNED(autoload_mutex);
2311 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2312
2313 VALUE autoload_data_value = rb_hash_aref(autoload_features, feature);
2315
2316 if (NIL_P(autoload_data_value)) {
2317 autoload_data_value = TypedData_Make_Struct(0, struct autoload_data, &autoload_data_type, autoload_data);
2318 autoload_data->feature = feature;
2319 autoload_data->mutex = Qnil;
2320 ccan_list_head_init(&autoload_data->constants);
2321
2322 if (autoload_data_pointer) *autoload_data_pointer = autoload_data;
2323
2324 rb_hash_aset(autoload_features, feature, autoload_data_value);
2325 }
2326 else if (autoload_data_pointer) {
2327 *autoload_data_pointer = rb_check_typeddata(autoload_data_value, &autoload_data_type);
2328 }
2329
2330 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2331 return autoload_data_value;
2332}
2333
2334static struct st_table *
2335autoload_table_lookup_or_create(VALUE module)
2336{
2337 VALUE autoload_table_value = rb_ivar_lookup(module, autoload, 0);
2338 if (autoload_table_value) {
2339 return check_autoload_table(autoload_table_value);
2340 }
2341 else {
2342 autoload_table_value = TypedData_Wrap_Struct(0, &autoload_table_type, 0);
2343 rb_class_ivar_set(module, autoload, autoload_table_value);
2344 return (DATA_PTR(autoload_table_value) = st_init_numtable());
2345 }
2346}
2347
2348static VALUE
2349autoload_synchronized(VALUE _arguments)
2350{
2351 struct autoload_arguments *arguments = (struct autoload_arguments *)_arguments;
2352
2353 rb_const_entry_t *constant_entry = rb_const_lookup(arguments->module, arguments->name);
2354 if (constant_entry && !UNDEF_P(constant_entry->value)) {
2355 return Qfalse;
2356 }
2357
2358 // Reset any state associated with any previous constant:
2359 const_set(arguments->module, arguments->name, Qundef);
2360
2361 struct st_table *autoload_table = autoload_table_lookup_or_create(arguments->module);
2362
2363 // Ensure the string is uniqued since we use an identity lookup:
2364 VALUE feature = rb_fstring(arguments->feature);
2365
2367 VALUE autoload_data_value = autoload_feature_lookup_or_create(feature, &autoload_data);
2368
2369 {
2371 VALUE autoload_const_value = TypedData_Make_Struct(0, struct autoload_const, &autoload_const_type, autoload_const);
2372 autoload_const->module = arguments->module;
2373 autoload_const->name = arguments->name;
2374 autoload_const->value = Qundef;
2375 autoload_const->flag = CONST_PUBLIC;
2376 autoload_const->autoload_data_value = autoload_data_value;
2377 ccan_list_add_tail(&autoload_data->constants, &autoload_const->cnode);
2378 st_insert(autoload_table, (st_data_t)arguments->name, (st_data_t)autoload_const_value);
2379 }
2380
2381 return Qtrue;
2382}
2383
2384void
2385rb_autoload_str(VALUE module, ID name, VALUE feature)
2386{
2387 if (!rb_is_const_id(name)) {
2388 rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"", QUOTE_ID(name));
2389 }
2390
2391 Check_Type(feature, T_STRING);
2392 if (!RSTRING_LEN(feature)) {
2393 rb_raise(rb_eArgError, "empty feature name");
2394 }
2395
2396 struct autoload_arguments arguments = {
2397 .module = module,
2398 .name = name,
2399 .feature = feature,
2400 };
2401
2402 VALUE result = rb_mutex_synchronize(autoload_mutex, autoload_synchronized, (VALUE)&arguments);
2403
2404 if (result == Qtrue) {
2405 const_added(module, name);
2406 }
2407}
2408
2409static void
2410autoload_delete(VALUE module, ID name)
2411{
2412 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2413
2414 st_data_t load = 0, key = name;
2415
2416 RUBY_ASSERT(RB_TYPE_P(module, T_CLASS) || RB_TYPE_P(module, T_MODULE));
2417
2418 VALUE table_value = rb_ivar_lookup(module, autoload, 0);
2419 if (table_value) {
2420 struct st_table *table = check_autoload_table(table_value);
2421
2422 st_delete(table, &key, &load);
2423
2424 /* Qfalse can indicate already deleted */
2425 if (load != Qfalse) {
2427 struct autoload_data *autoload_data = get_autoload_data((VALUE)load, &autoload_const);
2428
2429 VM_ASSERT(autoload_data);
2430 VM_ASSERT(!ccan_list_empty(&autoload_data->constants));
2431
2432 /*
2433 * we must delete here to avoid "already initialized" warnings
2434 * with parallel autoload. Using list_del_init here so list_del
2435 * works in autoload_const_free
2436 */
2437 ccan_list_del_init(&autoload_const->cnode);
2438
2439 if (ccan_list_empty(&autoload_data->constants)) {
2440 rb_hash_delete(autoload_features, autoload_data->feature);
2441 }
2442
2443 // If the autoload table is empty, we can delete it.
2444 if (table->num_entries == 0) {
2445 rb_attr_delete(module, autoload);
2446 }
2447 }
2448 }
2449
2450 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2451}
2452
2453static int
2454autoload_by_someone_else(struct autoload_data *ele)
2455{
2456 return ele->mutex != Qnil && !rb_mutex_owned_p(ele->mutex);
2457}
2458
2459static VALUE
2460check_autoload_required(VALUE mod, ID id, const char **loadingpath)
2461{
2462 VALUE autoload_const_value = autoload_data(mod, id);
2464 const char *loading;
2465
2466 if (!autoload_const_value || !(autoload_data = get_autoload_data(autoload_const_value, 0))) {
2467 return 0;
2468 }
2469
2470 VALUE feature = autoload_data->feature;
2471
2472 /*
2473 * if somebody else is autoloading, we MUST wait for them, since
2474 * rb_provide_feature can provide a feature before autoload_const_set
2475 * completes. We must wait until autoload_const_set finishes in
2476 * the other thread.
2477 */
2478 if (autoload_by_someone_else(autoload_data)) {
2479 return autoload_const_value;
2480 }
2481
2482 loading = RSTRING_PTR(feature);
2483
2484 if (!rb_feature_provided(loading, &loading)) {
2485 return autoload_const_value;
2486 }
2487
2488 if (loadingpath && loading) {
2489 *loadingpath = loading;
2490 return autoload_const_value;
2491 }
2492
2493 return 0;
2494}
2495
2496static struct autoload_const *autoloading_const_entry(VALUE mod, ID id);
2497
2498MJIT_FUNC_EXPORTED int
2499rb_autoloading_value(VALUE mod, ID id, VALUE* value, rb_const_flag_t *flag)
2500{
2501 struct autoload_const *ac = autoloading_const_entry(mod, id);
2502 if (!ac) return FALSE;
2503
2504 if (value) {
2505 *value = ac->value;
2506 }
2507
2508 if (flag) {
2509 *flag = ac->flag;
2510 }
2511
2512 return TRUE;
2513}
2514
2515static int
2516autoload_by_current(struct autoload_data *ele)
2517{
2518 return ele->mutex != Qnil && rb_mutex_owned_p(ele->mutex);
2519}
2520
2521// If there is an autoloading constant and it has been set by the current
2522// execution context, return it. This allows threads which are loading code to
2523// refer to their own autoloaded constants.
2524struct autoload_const *
2525autoloading_const_entry(VALUE mod, ID id)
2526{
2527 VALUE load = autoload_data(mod, id);
2528 struct autoload_data *ele;
2529 struct autoload_const *ac;
2530
2531 // Find the autoloading state:
2532 if (!load || !(ele = get_autoload_data(load, &ac))) {
2533 // Couldn't be found:
2534 return 0;
2535 }
2536
2537 // Check if it's being loaded by the current thread/fiber:
2538 if (autoload_by_current(ele)) {
2539 if (!UNDEF_P(ac->value)) {
2540 return ac;
2541 }
2542 }
2543
2544 return 0;
2545}
2546
2547static int
2548autoload_defined_p(VALUE mod, ID id)
2549{
2550 rb_const_entry_t *ce = rb_const_lookup(mod, id);
2551
2552 // If there is no constant or the constant is not undefined (special marker for autoloading):
2553 if (!ce || !UNDEF_P(ce->value)) {
2554 // We are not autoloading:
2555 return 0;
2556 }
2557
2558 // Otherwise check if there is an autoload in flight right now:
2559 return !rb_autoloading_value(mod, id, NULL, NULL);
2560}
2561
2562static void const_tbl_update(struct autoload_const *, int);
2563
2565 VALUE module;
2566 ID name;
2567 int flag;
2568
2569 VALUE mutex;
2570
2571 // The specific constant which triggered the autoload code to fire:
2573
2574 // The parent autoload data which is shared between multiple constants:
2576};
2577
2578static VALUE
2579autoload_const_set(struct autoload_const *ac)
2580{
2581 check_before_mod_set(ac->module, ac->name, ac->value, "constant");
2582
2583 RB_VM_LOCK_ENTER();
2584 {
2585 const_tbl_update(ac, true);
2586 }
2587 RB_VM_LOCK_LEAVE();
2588
2589 return 0; /* ignored */
2590}
2591
2592static VALUE
2593autoload_load_needed(VALUE _arguments)
2594{
2595 struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments;
2596
2597 const char *loading = 0, *src;
2598
2599 if (!autoload_defined_p(arguments->module, arguments->name)) {
2600 return Qfalse;
2601 }
2602
2603 VALUE autoload_const_value = check_autoload_required(arguments->module, arguments->name, &loading);
2604 if (!autoload_const_value) {
2605 return Qfalse;
2606 }
2607
2608 src = rb_sourcefile();
2609 if (src && loading && strcmp(src, loading) == 0) {
2610 return Qfalse;
2611 }
2612
2615 if (!(autoload_data = get_autoload_data(autoload_const_value, &autoload_const))) {
2616 return Qfalse;
2617 }
2618
2619 if (NIL_P(autoload_data->mutex)) {
2620 autoload_data->mutex = rb_mutex_new();
2621 autoload_data->fork_gen = GET_VM()->fork_gen;
2622 }
2623 else if (rb_mutex_owned_p(autoload_data->mutex)) {
2624 return Qfalse;
2625 }
2626
2627 arguments->mutex = autoload_data->mutex;
2628 arguments->autoload_const = autoload_const;
2629
2630 return autoload_const_value;
2631}
2632
2633static VALUE
2634autoload_apply_constants(VALUE _arguments)
2635{
2636 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
2637
2638 struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments;
2639
2640 struct autoload_const *autoload_const = 0; // for ccan_container_off_var()
2641 struct autoload_const *next;
2642
2643 // We use safe iteration here because `autoload_const_set` will eventually invoke
2644 // `autoload_delete` which will remove the constant from the linked list. In theory, once
2645 // the `autoload_data->constants` linked list is empty, we can remove it.
2646
2647 // Iterate over all constants and assign them:
2648 ccan_list_for_each_safe(&arguments->autoload_data->constants, autoload_const, next, cnode) {
2649 if (!UNDEF_P(autoload_const->value)) {
2650 autoload_const_set(autoload_const);
2651 }
2652 }
2653
2654 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
2655
2656 return Qtrue;
2657}
2658
2659static VALUE
2660autoload_feature_require(VALUE _arguments)
2661{
2662 struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments;
2663
2664 struct autoload_const *autoload_const = arguments->autoload_const;
2665
2666 // We save this for later use in autoload_apply_constants:
2667 arguments->autoload_data = rb_check_typeddata(autoload_const->autoload_data_value, &autoload_data_type);
2668
2669 VALUE result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1, arguments->autoload_data->feature);
2670
2671 if (RTEST(result)) {
2672 return rb_mutex_synchronize(autoload_mutex, autoload_apply_constants, _arguments);
2673 }
2674
2675 return result;
2676}
2677
2678static VALUE
2679autoload_try_load(VALUE _arguments)
2680{
2681 struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments;
2682
2683 VALUE result = autoload_feature_require(_arguments);
2684
2685 // After we loaded the feature, if the constant is not defined, we remove it completely:
2686 rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name);
2687
2688 if (!ce || UNDEF_P(ce->value)) {
2689 result = Qfalse;
2690
2691 rb_const_remove(arguments->module, arguments->name);
2692
2693 if (arguments->module == rb_cObject) {
2694 rb_warning(
2695 "Expected %"PRIsVALUE" to define %"PRIsVALUE" but it didn't",
2696 arguments->autoload_data->feature,
2697 ID2SYM(arguments->name)
2698 );
2699 }
2700 else {
2701 rb_warning(
2702 "Expected %"PRIsVALUE" to define %"PRIsVALUE"::%"PRIsVALUE" but it didn't",
2703 arguments->autoload_data->feature,
2704 arguments->module,
2705 ID2SYM(arguments->name)
2706 );
2707 }
2708 }
2709 else {
2710 // Otherwise, it was loaded, copy the flags from the autoload constant:
2711 ce->flag |= arguments->flag;
2712 }
2713
2714 return result;
2715}
2716
2717VALUE
2719{
2720 rb_const_entry_t *ce = rb_const_lookup(module, name);
2721
2722 // We bail out as early as possible without any synchronisation:
2723 if (!ce || !UNDEF_P(ce->value)) {
2724 return Qfalse;
2725 }
2726
2727 // At this point, we assume there might be autoloading, so fail if it's ractor:
2728 if (UNLIKELY(!rb_ractor_main_p())) {
2729 rb_raise(rb_eRactorUnsafeError, "require by autoload on non-main Ractor is not supported (%s)", rb_id2name(name));
2730 }
2731
2732 // This state is stored on thes stack and is used during the autoload process.
2733 struct autoload_load_arguments arguments = {.module = module, .name = name, .mutex = Qnil};
2734
2735 // Figure out whether we can autoload the named constant:
2736 VALUE autoload_const_value = rb_mutex_synchronize(autoload_mutex, autoload_load_needed, (VALUE)&arguments);
2737
2738 // This confirms whether autoloading is required or not:
2739 if (autoload_const_value == Qfalse) return autoload_const_value;
2740
2741 arguments.flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2742
2743 // Only one thread will enter here at a time:
2744 VALUE result = rb_mutex_synchronize(arguments.mutex, autoload_try_load, (VALUE)&arguments);
2745
2746 // If you don't guard this value, it's possible for the autoload constant to
2747 // be freed by another thread which loads multiple constants, one of which
2748 // resolves to the constant this thread is trying to load, so proteect this
2749 // so that it is not freed until we are done with it in `autoload_try_load`:
2750 RB_GC_GUARD(autoload_const_value);
2751
2752 return result;
2753}
2754
2755VALUE
2757{
2758 return rb_autoload_at_p(mod, id, TRUE);
2759}
2760
2761VALUE
2762rb_autoload_at_p(VALUE mod, ID id, int recur)
2763{
2764 VALUE load;
2765 struct autoload_data *ele;
2766
2767 while (!autoload_defined_p(mod, id)) {
2768 if (!recur) return Qnil;
2769 mod = RCLASS_SUPER(mod);
2770 if (!mod) return Qnil;
2771 }
2772 load = check_autoload_required(mod, id, 0);
2773 if (!load) return Qnil;
2774 return (ele = get_autoload_data(load, 0)) ? ele->feature : Qnil;
2775}
2776
2777MJIT_FUNC_EXPORTED void
2778rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
2779{
2780 if (RB_CONST_DEPRECATED_P(ce) &&
2781 rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
2782 if (klass == rb_cObject) {
2783 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
2784 }
2785 else {
2786 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
2787 rb_class_name(klass), QUOTE_ID(id));
2788 }
2789 }
2790}
2791
2792static VALUE
2793rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2794{
2795 VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
2796 if (!UNDEF_P(c)) {
2797 if (UNLIKELY(!rb_ractor_main_p())) {
2798 if (!rb_ractor_shareable_p(c)) {
2799 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));
2800 }
2801 }
2802 return c;
2803 }
2804 return rb_const_missing(klass, ID2SYM(id));
2805}
2806
2807static VALUE
2808rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2809{
2810 VALUE value, current;
2811 bool first_iteration = true;
2812
2813 for (current = klass;
2814 RTEST(current);
2815 current = RCLASS_SUPER(current), first_iteration = false) {
2816 VALUE tmp;
2817 VALUE am = 0;
2818 rb_const_entry_t *ce;
2819
2820 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
2821 // This item in the super chain has an origin iclass
2822 // that comes later in the chain. Skip this item so
2823 // prepended modules take precedence.
2824 continue;
2825 }
2826
2827 // Do lookup in original class or module in case we are at an origin
2828 // iclass in the chain.
2829 tmp = current;
2830 if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass;
2831
2832 // Do the lookup. Loop in case of autoload.
2833 while ((ce = rb_const_lookup(tmp, id))) {
2834 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2835 GET_EC()->private_const_reference = tmp;
2836 return Qundef;
2837 }
2838 rb_const_warn_if_deprecated(ce, tmp, id);
2839 value = ce->value;
2840 if (UNDEF_P(value)) {
2841 struct autoload_const *ac;
2842 if (am == tmp) break;
2843 am = tmp;
2844 ac = autoloading_const_entry(tmp, id);
2845 if (ac) return ac->value;
2846 rb_autoload_load(tmp, id);
2847 continue;
2848 }
2849 if (exclude && tmp == rb_cObject) {
2850 goto not_found;
2851 }
2852 return value;
2853 }
2854 if (!recurse) break;
2855 }
2856
2857 not_found:
2858 GET_EC()->private_const_reference = 0;
2859 return Qundef;
2860}
2861
2862static VALUE
2863rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
2864{
2865 VALUE value;
2866
2867 if (klass == rb_cObject) exclude = FALSE;
2868 value = rb_const_search_from(klass, id, exclude, recurse, visibility);
2869 if (!UNDEF_P(value)) return value;
2870 if (exclude) return value;
2871 if (BUILTIN_TYPE(klass) != T_MODULE) return value;
2872 /* search global const too, if klass is a module */
2873 return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
2874}
2875
2876VALUE
2878{
2879 return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
2880}
2881
2882VALUE
2884{
2885 return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
2886}
2887
2888VALUE
2890{
2891 return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
2892}
2893
2894MJIT_FUNC_EXPORTED VALUE
2895rb_public_const_get_from(VALUE klass, ID id)
2896{
2897 return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
2898}
2899
2900MJIT_FUNC_EXPORTED VALUE
2901rb_public_const_get_at(VALUE klass, ID id)
2902{
2903 return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
2904}
2905
2906NORETURN(static void undefined_constant(VALUE mod, VALUE name));
2907static void
2908undefined_constant(VALUE mod, VALUE name)
2909{
2910 rb_name_err_raise("constant %2$s::%1$s not defined",
2911 mod, name);
2912}
2913
2914static VALUE
2915rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2916{
2917 while (RTEST(klass)) {
2918 rb_const_entry_t *ce;
2919
2920 while ((ce = rb_const_lookup(klass, id))) {
2921 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2922 return Qnil;
2923 }
2924 if (exclude && klass == rb_cObject) {
2925 goto not_found;
2926 }
2927 if (NIL_P(ce->file)) return rb_ary_new();
2928 return rb_assoc_new(ce->file, INT2NUM(ce->line));
2929 }
2930 if (!recurse) break;
2931 klass = RCLASS_SUPER(klass);
2932 }
2933
2934 not_found:
2935 return Qnil;
2936}
2937
2938static VALUE
2939rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility)
2940{
2941 VALUE loc;
2942
2943 if (klass == rb_cObject) exclude = FALSE;
2944 loc = rb_const_location_from(klass, id, exclude, recurse, visibility);
2945 if (!NIL_P(loc)) return loc;
2946 if (exclude) return loc;
2947 if (BUILTIN_TYPE(klass) != T_MODULE) return loc;
2948 /* search global const too, if klass is a module */
2949 return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility);
2950}
2951
2952VALUE
2953rb_const_source_location(VALUE klass, ID id)
2954{
2955 return rb_const_location(klass, id, FALSE, TRUE, FALSE);
2956}
2957
2958MJIT_FUNC_EXPORTED VALUE
2959rb_const_source_location_at(VALUE klass, ID id)
2960{
2961 return rb_const_location(klass, id, TRUE, FALSE, FALSE);
2962}
2963
2964/*
2965 * call-seq:
2966 * remove_const(sym) -> obj
2967 *
2968 * Removes the definition of the given constant, returning that
2969 * constant's previous value. If that constant referred to
2970 * a module, this will not change that module's name and can lead
2971 * to confusion.
2972 */
2973
2974VALUE
2976{
2977 const ID id = id_for_var(mod, name, a, constant);
2978
2979 if (!id) {
2980 undefined_constant(mod, name);
2981 }
2982 return rb_const_remove(mod, id);
2983}
2984
2985VALUE
2987{
2988 VALUE val;
2989 rb_const_entry_t *ce;
2990
2991 rb_check_frozen(mod);
2992
2993 ce = rb_const_lookup(mod, id);
2994 if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2995 if (rb_const_defined_at(mod, id)) {
2996 rb_name_err_raise("cannot remove %2$s::%1$s", mod, ID2SYM(id));
2997 }
2998
2999 undefined_constant(mod, ID2SYM(id));
3000 }
3001
3003
3004 val = ce->value;
3005
3006 if (UNDEF_P(val)) {
3007 autoload_delete(mod, id);
3008 val = Qnil;
3009 }
3010
3011 ruby_xfree(ce);
3012
3013 return val;
3014}
3015
3016static int
3017cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
3018{
3019 if (existing) return ST_STOP;
3020 *v = a;
3021 return ST_CONTINUE;
3022}
3023
3024static enum rb_id_table_iterator_result
3025sv_i(ID key, VALUE v, void *a)
3026{
3028 st_table *tbl = a;
3029
3030 if (rb_is_const_id(key)) {
3031 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
3032 }
3033 return ID_TABLE_CONTINUE;
3034}
3035
3036static enum rb_id_table_iterator_result
3037rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
3038{
3039 if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
3040 rb_ary_push((VALUE)ary, ID2SYM(const_name));
3041 }
3042 return ID_TABLE_CONTINUE;
3043}
3044
3045static VALUE
3046rb_local_constants(VALUE mod)
3047{
3048 struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
3049 VALUE ary;
3050
3051 if (!tbl) return rb_ary_new2(0);
3052
3053 RB_VM_LOCK_ENTER();
3054 {
3055 ary = rb_ary_new2(rb_id_table_size(tbl));
3056 rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
3057 }
3058 RB_VM_LOCK_LEAVE();
3059
3060 return ary;
3061}
3062
3063void*
3064rb_mod_const_at(VALUE mod, void *data)
3065{
3066 st_table *tbl = data;
3067 if (!tbl) {
3068 tbl = st_init_numtable();
3069 }
3070 if (RCLASS_CONST_TBL(mod)) {
3071 RB_VM_LOCK_ENTER();
3072 {
3073 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
3074 }
3075 RB_VM_LOCK_LEAVE();
3076 }
3077 return tbl;
3078}
3079
3080void*
3081rb_mod_const_of(VALUE mod, void *data)
3082{
3083 VALUE tmp = mod;
3084 for (;;) {
3085 data = rb_mod_const_at(tmp, data);
3086 tmp = RCLASS_SUPER(tmp);
3087 if (!tmp) break;
3088 if (tmp == rb_cObject && mod != rb_cObject) break;
3089 }
3090 return data;
3091}
3092
3093static int
3094list_i(st_data_t key, st_data_t value, VALUE ary)
3095{
3096 ID sym = (ID)key;
3097 rb_const_entry_t *ce = (rb_const_entry_t *)value;
3098 if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
3099 return ST_CONTINUE;
3100}
3101
3102VALUE
3103rb_const_list(void *data)
3104{
3105 st_table *tbl = data;
3106 VALUE ary;
3107
3108 if (!tbl) return rb_ary_new2(0);
3109 ary = rb_ary_new2(tbl->num_entries);
3110 st_foreach_safe(tbl, list_i, ary);
3111 st_free_table(tbl);
3112
3113 return ary;
3114}
3115
3116/*
3117 * call-seq:
3118 * mod.constants(inherit=true) -> array
3119 *
3120 * Returns an array of the names of the constants accessible in
3121 * <i>mod</i>. This includes the names of constants in any included
3122 * modules (example at start of section), unless the <i>inherit</i>
3123 * parameter is set to <code>false</code>.
3124 *
3125 * The implementation makes no guarantees about the order in which the
3126 * constants are yielded.
3127 *
3128 * IO.constants.include?(:SYNC) #=> true
3129 * IO.constants(false).include?(:SYNC) #=> false
3130 *
3131 * Also see Module#const_defined?.
3132 */
3133
3134VALUE
3135rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
3136{
3137 bool inherit = true;
3138
3139 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3140
3141 if (inherit) {
3142 return rb_const_list(rb_mod_const_of(mod, 0));
3143 }
3144 else {
3145 return rb_local_constants(mod);
3146 }
3147}
3148
3149static int
3150rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
3151{
3152 VALUE tmp;
3153 int mod_retry = 0;
3154 rb_const_entry_t *ce;
3155
3156 tmp = klass;
3157 retry:
3158 while (tmp) {
3159 if ((ce = rb_const_lookup(tmp, id))) {
3160 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3161 return (int)Qfalse;
3162 }
3163 if (UNDEF_P(ce->value) && !check_autoload_required(tmp, id, 0) &&
3164 !rb_autoloading_value(tmp, id, NULL, NULL))
3165 return (int)Qfalse;
3166
3167 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3168 return (int)Qfalse;
3169 }
3170
3171 return (int)Qtrue;
3172 }
3173 if (!recurse) break;
3174 tmp = RCLASS_SUPER(tmp);
3175 }
3176 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
3177 mod_retry = 1;
3178 tmp = rb_cObject;
3179 goto retry;
3180 }
3181 return (int)Qfalse;
3182}
3183
3184int
3186{
3187 return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
3188}
3189
3190int
3192{
3193 return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
3194}
3195
3196int
3198{
3199 return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
3200}
3201
3202MJIT_FUNC_EXPORTED int
3203rb_public_const_defined_from(VALUE klass, ID id)
3204{
3205 return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
3206}
3207
3208static void
3209check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
3210{
3211 rb_check_frozen(klass);
3212}
3213
3214static void set_namespace_path(VALUE named_namespace, VALUE name);
3215
3216static enum rb_id_table_iterator_result
3217set_namespace_path_i(ID id, VALUE v, void *payload)
3218{
3220 VALUE value = ce->value;
3221 int has_permanent_classpath;
3222 VALUE parental_path = *((VALUE *) payload);
3223 if (!rb_is_const_id(id) || !rb_namespace_p(value)) {
3224 return ID_TABLE_CONTINUE;
3225 }
3226 classname(value, &has_permanent_classpath);
3227 if (has_permanent_classpath) {
3228 return ID_TABLE_CONTINUE;
3229 }
3230 set_namespace_path(value, build_const_path(parental_path, id));
3231 rb_attr_delete(value, tmp_classpath);
3232
3233 return ID_TABLE_CONTINUE;
3234}
3235
3236/*
3237 * Assign permanent classpaths to all namespaces that are directly or indirectly
3238 * nested under +named_namespace+. +named_namespace+ must have a permanent
3239 * classpath.
3240 */
3241static void
3242set_namespace_path(VALUE named_namespace, VALUE namespace_path)
3243{
3244 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3245
3246 RB_VM_LOCK_ENTER();
3247 {
3248 rb_class_ivar_set(named_namespace, classpath, namespace_path);
3249 if (const_table) {
3250 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3251 }
3252 }
3253 RB_VM_LOCK_LEAVE();
3254}
3255
3256static void
3257const_added(VALUE klass, ID const_name)
3258{
3259 if (GET_VM()->running) {
3260 VALUE name = ID2SYM(const_name);
3261 rb_funcallv(klass, idConst_added, 1, &name);
3262 }
3263}
3264
3265static void
3266const_set(VALUE klass, ID id, VALUE val)
3267{
3268 rb_const_entry_t *ce;
3269
3270 if (NIL_P(klass)) {
3271 rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
3272 QUOTE_ID(id));
3273 }
3274
3275 if (!rb_ractor_main_p() && !rb_ractor_shareable_p(val)) {
3276 rb_raise(rb_eRactorIsolationError, "can not set constants with non-shareable objects by non-main Ractors");
3277 }
3278
3279 check_before_mod_set(klass, id, val, "constant");
3280
3281 RB_VM_LOCK_ENTER();
3282 {
3283 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3284 if (!tbl) {
3285 RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
3288 rb_id_table_insert(tbl, id, (VALUE)ce);
3289 setup_const_entry(ce, klass, val, CONST_PUBLIC);
3290 }
3291 else {
3292 struct autoload_const ac = {
3293 .module = klass, .name = id,
3294 .value = val, .flag = CONST_PUBLIC,
3295 /* fill the rest with 0 */
3296 };
3297 ac.file = rb_source_location(&ac.line);
3298 const_tbl_update(&ac, false);
3299 }
3300 }
3301 RB_VM_LOCK_LEAVE();
3302
3303 /*
3304 * Resolve and cache class name immediately to resolve ambiguity
3305 * and avoid order-dependency on const_tbl
3306 */
3307 if (rb_cObject && rb_namespace_p(val)) {
3308 int val_path_permanent;
3309 VALUE val_path = classname(val, &val_path_permanent);
3310 if (NIL_P(val_path) || !val_path_permanent) {
3311 if (klass == rb_cObject) {
3312 set_namespace_path(val, rb_id2str(id));
3313 }
3314 else {
3315 int parental_path_permanent;
3316 VALUE parental_path = classname(klass, &parental_path_permanent);
3317 if (NIL_P(parental_path)) {
3318 int throwaway;
3319 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
3320 }
3321 if (parental_path_permanent && !val_path_permanent) {
3322 set_namespace_path(val, build_const_path(parental_path, id));
3323 }
3324 else if (!parental_path_permanent && NIL_P(val_path)) {
3325 ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
3326 }
3327 }
3328 }
3329 }
3330}
3331
3332void
3334{
3335 const_set(klass, id, val);
3336 const_added(klass, id);
3337}
3338
3339static struct autoload_data *
3340autoload_data_for_named_constant(VALUE module, ID name, struct autoload_const **autoload_const_pointer)
3341{
3342 VALUE autoload_data_value = autoload_data(module, name);
3343 if (!autoload_data_value) return 0;
3344
3345 struct autoload_data *autoload_data = get_autoload_data(autoload_data_value, autoload_const_pointer);
3346 if (!autoload_data) return 0;
3347
3348 /* for autoloading thread, keep the defined value to autoloading storage */
3349 if (autoload_by_current(autoload_data)) {
3350 return autoload_data;
3351 }
3352
3353 return 0;
3354}
3355
3356static void
3357const_tbl_update(struct autoload_const *ac, int autoload_force)
3358{
3359 VALUE value;
3360 VALUE klass = ac->module;
3361 VALUE val = ac->value;
3362 ID id = ac->name;
3363 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3364 rb_const_flag_t visibility = ac->flag;
3365 rb_const_entry_t *ce;
3366
3367 if (rb_id_table_lookup(tbl, id, &value)) {
3368 ce = (rb_const_entry_t *)value;
3369 if (UNDEF_P(ce->value)) {
3370 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3371 VALUE file = ac->file;
3372 int line = ac->line;
3373 struct autoload_data *ele = autoload_data_for_named_constant(klass, id, &ac);
3374
3375 if (!autoload_force && ele) {
3377
3378 ac->value = val; /* autoload_data is non-WB-protected */
3379 ac->file = rb_source_location(&ac->line);
3380 }
3381 else {
3382 /* otherwise autoloaded constant, allow to override */
3383 autoload_delete(klass, id);
3384 ce->flag = visibility;
3385 RB_OBJ_WRITE(klass, &ce->value, val);
3386 RB_OBJ_WRITE(klass, &ce->file, file);
3387 ce->line = line;
3388 }
3389 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3390 return;
3391 }
3392 else {
3393 VALUE name = QUOTE_ID(id);
3394 visibility = ce->flag;
3395 if (klass == rb_cObject)
3396 rb_warn("already initialized constant %"PRIsVALUE"", name);
3397 else
3398 rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
3399 rb_class_name(klass), name);
3400 if (!NIL_P(ce->file) && ce->line) {
3401 rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
3402 "previous definition of %"PRIsVALUE" was here", name);
3403 }
3404 }
3406 setup_const_entry(ce, klass, val, visibility);
3407 }
3408 else {
3410
3412 rb_id_table_insert(tbl, id, (VALUE)ce);
3413 setup_const_entry(ce, klass, val, visibility);
3414 }
3415}
3416
3417static void
3418setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
3419 rb_const_flag_t visibility)
3420{
3421 ce->flag = visibility;
3422 RB_OBJ_WRITE(klass, &ce->value, val);
3423 RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
3424}
3425
3426void
3427rb_define_const(VALUE klass, const char *name, VALUE val)
3428{
3429 ID id = rb_intern(name);
3430
3431 if (!rb_is_const_id(id)) {
3432 rb_warn("rb_define_const: invalid name `%s' for constant", name);
3433 }
3434 rb_gc_register_mark_object(val);
3435 rb_const_set(klass, id, val);
3436}
3437
3438void
3439rb_define_global_const(const char *name, VALUE val)
3440{
3441 rb_define_const(rb_cObject, name, val);
3442}
3443
3444static void
3445set_const_visibility(VALUE mod, int argc, const VALUE *argv,
3446 rb_const_flag_t flag, rb_const_flag_t mask)
3447{
3448 int i;
3449 rb_const_entry_t *ce;
3450 ID id;
3451
3453 if (argc == 0) {
3454 rb_warning("%"PRIsVALUE" with no argument is just ignored",
3455 QUOTE_ID(rb_frame_callee()));
3456 return;
3457 }
3458
3459 for (i = 0; i < argc; i++) {
3460 struct autoload_const *ac;
3461 VALUE val = argv[i];
3462 id = rb_check_id(&val);
3463 if (!id) {
3464 undefined_constant(mod, val);
3465 }
3466 if ((ce = rb_const_lookup(mod, id))) {
3467 ce->flag &= ~mask;
3468 ce->flag |= flag;
3469 if (UNDEF_P(ce->value)) {
3470 struct autoload_data *ele;
3471
3472 ele = autoload_data_for_named_constant(mod, id, &ac);
3473 if (ele) {
3474 ac->flag &= ~mask;
3475 ac->flag |= flag;
3476 }
3477 }
3479 }
3480 else {
3481 undefined_constant(mod, ID2SYM(id));
3482 }
3483 }
3484}
3485
3486void
3487rb_deprecate_constant(VALUE mod, const char *name)
3488{
3489 rb_const_entry_t *ce;
3490 ID id;
3491 long len = strlen(name);
3492
3494 if (!(id = rb_check_id_cstr(name, len, NULL))) {
3495 undefined_constant(mod, rb_fstring_new(name, len));
3496 }
3497 if (!(ce = rb_const_lookup(mod, id))) {
3498 undefined_constant(mod, ID2SYM(id));
3499 }
3500 ce->flag |= CONST_DEPRECATED;
3501}
3502
3503/*
3504 * call-seq:
3505 * mod.private_constant(symbol, ...) => mod
3506 *
3507 * Makes a list of existing constants private.
3508 */
3509
3510VALUE
3511rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
3512{
3513 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
3514 return obj;
3515}
3516
3517/*
3518 * call-seq:
3519 * mod.public_constant(symbol, ...) => mod
3520 *
3521 * Makes a list of existing constants public.
3522 */
3523
3524VALUE
3525rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
3526{
3527 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
3528 return obj;
3529}
3530
3531/*
3532 * call-seq:
3533 * mod.deprecate_constant(symbol, ...) => mod
3534 *
3535 * Makes a list of existing constants deprecated. Attempt
3536 * to refer to them will produce a warning.
3537 *
3538 * module HTTP
3539 * NotFound = Exception.new
3540 * NOT_FOUND = NotFound # previous version of the library used this name
3541 *
3542 * deprecate_constant :NOT_FOUND
3543 * end
3544 *
3545 * HTTP::NOT_FOUND
3546 * # warning: constant HTTP::NOT_FOUND is deprecated
3547 *
3548 */
3549
3550VALUE
3551rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
3552{
3553 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3554 return obj;
3555}
3556
3557static VALUE
3558original_module(VALUE c)
3559{
3560 if (RB_TYPE_P(c, T_ICLASS))
3561 return RBASIC(c)->klass;
3562 return c;
3563}
3564
3565static int
3566cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3567{
3568 if (RB_TYPE_P(klass, T_ICLASS)) {
3569 if (FL_TEST_RAW(klass, RICLASS_IS_ORIGIN)) {
3570 return 0;
3571 }
3572 else {
3573 // check the original module
3574 klass = RBASIC(klass)->klass;
3575 }
3576 }
3577
3578 VALUE n = rb_ivar_lookup(klass, id, Qundef);
3579 if (UNDEF_P(n)) return 0;
3580
3581 if (v) *v = n;
3582 return 1;
3583}
3584
3585static VALUE
3586cvar_front_klass(VALUE klass)
3587{
3588 if (FL_TEST(klass, FL_SINGLETON)) {
3589 VALUE obj = rb_ivar_get(klass, id__attached__);
3590 if (rb_namespace_p(obj)) {
3591 return obj;
3592 }
3593 }
3594 return RCLASS_SUPER(klass);
3595}
3596
3597static void
3598cvar_overtaken(VALUE front, VALUE target, ID id)
3599{
3600 if (front && target != front) {
3601 if (original_module(front) != original_module(target)) {
3603 "class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3604 ID2SYM(id), rb_class_name(original_module(front)),
3605 rb_class_name(original_module(target)));
3606 }
3607 if (BUILTIN_TYPE(front) == T_CLASS) {
3608 rb_ivar_delete(front, id, Qundef);
3609 }
3610 }
3611}
3612
3613static VALUE
3614find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id)
3615{
3616 VALUE v = Qundef;
3617 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR();
3618 if (cvar_lookup_at(klass, id, (&v))) {
3619 if (!*front) {
3620 *front = klass;
3621 }
3622 *target = klass;
3623 }
3624
3625 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) {
3626 if (cvar_lookup_at(klass, id, (&v))) {
3627 if (!*front) {
3628 *front = klass;
3629 }
3630 *target = klass;
3631 }
3632 }
3633
3634 return v;
3635}
3636
3637#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3638 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3639 if (cvar_lookup_at(klass, id, (v))) { \
3640 r; \
3641 } \
3642 }
3643
3644#define CVAR_LOOKUP(v,r) do {\
3645 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
3646 if (cvar_lookup_at(klass, id, (v))) {r;}\
3647 CVAR_FOREACH_ANCESTORS(klass, v, r);\
3648} while(0)
3649
3650static void
3651check_for_cvar_table(VALUE subclass, VALUE key)
3652{
3653 // Must not check ivar on ICLASS
3654 if (!RB_TYPE_P(subclass, T_ICLASS) && RTEST(rb_ivar_defined(subclass, key))) {
3655 RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
3656 ruby_vm_global_cvar_state++;
3657 return;
3658 }
3659
3660 rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
3661}
3662
3663void
3664rb_cvar_set(VALUE klass, ID id, VALUE val)
3665{
3666 VALUE tmp, front = 0, target = 0;
3667
3668 tmp = klass;
3669 CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3670 if (target) {
3671 cvar_overtaken(front, target, id);
3672 }
3673 else {
3674 target = tmp;
3675 }
3676
3677 if (RB_TYPE_P(target, T_ICLASS)) {
3678 target = RBASIC(target)->klass;
3679 }
3680 check_before_mod_set(target, id, val, "class variable");
3681
3682 int result = rb_class_ivar_set(target, id, val);
3683
3684 struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
3685
3686 if (!rb_cvc_tbl) {
3687 rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
3688 }
3689
3690 struct rb_cvar_class_tbl_entry *ent;
3691 VALUE ent_data;
3692
3693 if (!rb_id_table_lookup(rb_cvc_tbl, id, &ent_data)) {
3694 ent = ALLOC(struct rb_cvar_class_tbl_entry);
3695 ent->class_value = target;
3696 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3697 rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent);
3698 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
3699 }
3700 else {
3701 ent = (void *)ent_data;
3702 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3703 }
3704
3705 // Break the cvar cache if this is a new class variable
3706 // and target is a module or a subclass with the same
3707 // cvar in this lookup.
3708 if (result == 0) {
3709 if (RB_TYPE_P(target, T_CLASS)) {
3710 if (RCLASS_SUBCLASSES(target)) {
3711 rb_class_foreach_subclass(target, check_for_cvar_table, id);
3712 }
3713 }
3714 }
3715}
3716
3717VALUE
3718rb_cvar_find(VALUE klass, ID id, VALUE *front)
3719{
3720 VALUE target = 0;
3721 VALUE value;
3722
3723 value = find_cvar(klass, front, &target, id);
3724 if (!target) {
3725 rb_name_err_raise("uninitialized class variable %1$s in %2$s",
3726 klass, ID2SYM(id));
3727 }
3728 cvar_overtaken(*front, target, id);
3729 return (VALUE)value;
3730}
3731
3732VALUE
3734{
3735 VALUE front = 0;
3736 return rb_cvar_find(klass, id, &front);
3737}
3738
3739VALUE
3741{
3742 if (!klass) return Qfalse;
3743 CVAR_LOOKUP(0,return Qtrue);
3744 return Qfalse;
3745}
3746
3747static ID
3748cv_intern(VALUE klass, const char *name)
3749{
3750 ID id = rb_intern(name);
3751 if (!rb_is_class_id(id)) {
3752 rb_name_err_raise("wrong class variable name %1$s",
3753 klass, rb_str_new_cstr(name));
3754 }
3755 return id;
3756}
3757
3758void
3759rb_cv_set(VALUE klass, const char *name, VALUE val)
3760{
3761 ID id = cv_intern(klass, name);
3762 rb_cvar_set(klass, id, val);
3763}
3764
3765VALUE
3766rb_cv_get(VALUE klass, const char *name)
3767{
3768 ID id = cv_intern(klass, name);
3769 return rb_cvar_get(klass, id);
3770}
3771
3772void
3773rb_define_class_variable(VALUE klass, const char *name, VALUE val)
3774{
3775 rb_cv_set(klass, name, val);
3776}
3777
3778static int
3779cv_i(st_data_t k, st_data_t v, st_data_t a)
3780{
3781 ID key = (ID)k;
3782 st_table *tbl = (st_table *)a;
3783
3784 if (rb_is_class_id(key)) {
3785 st_update(tbl, (st_data_t)key, cv_i_update, 0);
3786 }
3787 return ST_CONTINUE;
3788}
3789
3790static void*
3791mod_cvar_at(VALUE mod, void *data)
3792{
3793 st_table *tbl = data;
3794 if (!tbl) {
3795 tbl = st_init_numtable();
3796 }
3797 mod = original_module(mod);
3798
3799 rb_ivar_foreach(mod, cv_i, (st_data_t)tbl);
3800 return tbl;
3801}
3802
3803static void*
3804mod_cvar_of(VALUE mod, void *data)
3805{
3806 VALUE tmp = mod;
3807 if (FL_TEST(mod, FL_SINGLETON)) {
3808 if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) {
3809 data = mod_cvar_at(tmp, data);
3810 tmp = cvar_front_klass(tmp);
3811 }
3812 }
3813 for (;;) {
3814 data = mod_cvar_at(tmp, data);
3815 tmp = RCLASS_SUPER(tmp);
3816 if (!tmp) break;
3817 }
3818 return data;
3819}
3820
3821static int
3822cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3823{
3824 ID sym = (ID)key;
3825 rb_ary_push(ary, ID2SYM(sym));
3826 return ST_CONTINUE;
3827}
3828
3829static VALUE
3830cvar_list(void *data)
3831{
3832 st_table *tbl = data;
3833 VALUE ary;
3834
3835 if (!tbl) return rb_ary_new2(0);
3836 ary = rb_ary_new2(tbl->num_entries);
3837 st_foreach_safe(tbl, cv_list_i, ary);
3838 st_free_table(tbl);
3839
3840 return ary;
3841}
3842
3843/*
3844 * call-seq:
3845 * mod.class_variables(inherit=true) -> array
3846 *
3847 * Returns an array of the names of class variables in <i>mod</i>.
3848 * This includes the names of class variables in any included
3849 * modules, unless the <i>inherit</i> parameter is set to
3850 * <code>false</code>.
3851 *
3852 * class One
3853 * @@var1 = 1
3854 * end
3855 * class Two < One
3856 * @@var2 = 2
3857 * end
3858 * One.class_variables #=> [:@@var1]
3859 * Two.class_variables #=> [:@@var2, :@@var1]
3860 * Two.class_variables(false) #=> [:@@var2]
3861 */
3862
3863VALUE
3864rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
3865{
3866 bool inherit = true;
3867 st_table *tbl;
3868
3869 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3870 if (inherit) {
3871 tbl = mod_cvar_of(mod, 0);
3872 }
3873 else {
3874 tbl = mod_cvar_at(mod, 0);
3875 }
3876 return cvar_list(tbl);
3877}
3878
3879/*
3880 * call-seq:
3881 * remove_class_variable(sym) -> obj
3882 *
3883 * Removes the named class variable from the receiver, returning that
3884 * variable's value.
3885 *
3886 * class Example
3887 * @@var = 99
3888 * puts remove_class_variable(:@@var)
3889 * p(defined? @@var)
3890 * end
3891 *
3892 * <em>produces:</em>
3893 *
3894 * 99
3895 * nil
3896 */
3897
3898VALUE
3900{
3901 const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
3902 st_data_t val;
3903
3904 if (!id) {
3905 goto not_defined;
3906 }
3907 rb_check_frozen(mod);
3908 val = rb_ivar_delete(mod, id, Qundef);
3909 if (!UNDEF_P(val)) {
3910 return (VALUE)val;
3911 }
3912 if (rb_cvar_defined(mod, id)) {
3913 rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
3914 }
3915 not_defined:
3916 rb_name_err_raise("class variable %1$s not defined for %2$s",
3917 mod, name);
3919}
3920
3921VALUE
3922rb_iv_get(VALUE obj, const char *name)
3923{
3924 ID id = rb_check_id_cstr(name, strlen(name), rb_usascii_encoding());
3925
3926 if (!id) {
3927 return Qnil;
3928 }
3929 return rb_ivar_get(obj, id);
3930}
3931
3932VALUE
3933rb_iv_set(VALUE obj, const char *name, VALUE val)
3934{
3935 ID id = rb_intern(name);
3936
3937 return rb_ivar_set(obj, id, val);
3938}
3939
3940/* tbl = xx(obj); tbl[key] = value; */
3941int
3942rb_class_ivar_set(VALUE obj, ID key, VALUE value)
3943{
3944 RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
3945 int found;
3946
3947 RB_VM_LOCK_ENTER();
3948 {
3949 rb_shape_t * shape = rb_shape_get_shape(obj);
3950 attr_index_t idx;
3951 found = rb_shape_get_iv_index(shape, key, &idx);
3952
3953 if (found) {
3954 // Changing an existing instance variable
3955 RUBY_ASSERT(RCLASS_IVPTR(obj));
3956
3957 RCLASS_IVPTR(obj)[idx] = value;
3958 RB_OBJ_WRITTEN(obj, Qundef, value);
3959 }
3960 else {
3961 // Creating and setting a new instance variable
3962
3963 // Move to a shape which fits the new ivar
3964 idx = shape->next_iv_index;
3965 shape = rb_shape_get_next(shape, obj, key);
3966
3967 // We always allocate a power of two sized IV array. This way we
3968 // only need to realloc when we expand into a new power of two size
3969 if ((idx & (idx - 1)) == 0) {
3970 size_t newsize = idx ? idx * 2 : 1;
3971 REALLOC_N(RCLASS_IVPTR(obj), VALUE, newsize);
3972 }
3973
3974 RUBY_ASSERT(RCLASS_IVPTR(obj));
3975
3976 RB_OBJ_WRITE(obj, &RCLASS_IVPTR(obj)[idx], value);
3977 rb_shape_set_shape(obj, shape);
3978 }
3979 }
3980 RB_VM_LOCK_LEAVE();
3981
3982 return found;
3983}
3984
3985static int
3986tbl_copy_i(st_data_t key, st_data_t val, st_data_t dest)
3987{
3988 rb_class_ivar_set(dest, key, val);
3989
3990 return ST_CONTINUE;
3991}
3992
3993void
3994rb_iv_tbl_copy(VALUE dst, VALUE src)
3995{
3996 RUBY_ASSERT(rb_type(dst) == rb_type(src));
3997 RUBY_ASSERT(RB_TYPE_P(dst, T_CLASS) || RB_TYPE_P(dst, T_MODULE));
3998
3999 RUBY_ASSERT(RCLASS_SHAPE_ID(dst) == ROOT_SHAPE_ID || rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(dst))->type == SHAPE_INITIAL_CAPACITY);
4000 RUBY_ASSERT(!RCLASS_IVPTR(dst));
4001
4002 rb_ivar_foreach(src, tbl_copy_i, dst);
4003}
4004
4005MJIT_FUNC_EXPORTED rb_const_entry_t *
4006rb_const_lookup(VALUE klass, ID id)
4007{
4008 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4009
4010 if (tbl) {
4011 VALUE val;
4012 bool r;
4013 RB_VM_LOCK_ENTER();
4014 {
4015 r = rb_id_table_lookup(tbl, id, &val);
4016 }
4017 RB_VM_LOCK_LEAVE();
4018
4019 if (r) return (rb_const_entry_t *)val;
4020 }
4021 return NULL;
4022}
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:177
#define RUBY_EXTERN
Declaration of externally visible global variables.
Definition dllexport.h:47
void rb_obj_freeze_inline(VALUE obj)
Prevents further modifications to the given object.
Definition variable.c:1556
@ RUBY_FL_SINGLETON
This flag has something to do with an object's class.
Definition fl_type.h:430
void rb_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
Definition eval.c:431
void rb_freeze_singleton_class(VALUE x)
This is an implementation detail of RB_OBJ_FREEZE().
Definition class.c:2167
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition string.h:1675
#define FL_SINGLETON
Old name of RUBY_FL_SINGLETON.
Definition fl_type.h:58
#define FL_EXIVAR
Old name of RUBY_FL_EXIVAR.
Definition fl_type.h:67
#define REALLOC_N
Old name of RB_REALLOC_N.
Definition memory.h:397
#define ALLOC
Old name of RB_ALLOC.
Definition memory.h:394
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
#define Qundef
Old name of RUBY_Qundef.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
Definition fl_type.h:145
#define rb_str_cat2
Old name of rb_str_cat_cstr.
Definition string.h:1683
#define xrealloc
Old name of ruby_xrealloc.
Definition xmalloc.h:56
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:143
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
#define ZALLOC
Old name of RB_ZALLOC.
Definition memory.h:396
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:203
#define xmalloc
Old name of ruby_xmalloc.
Definition xmalloc.h:53
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition value_type.h:70
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:393
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:140
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h:137
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:652
#define Qtrue
Old name of RUBY_Qtrue.
#define INT2NUM
Old name of RB_INT2NUM.
Definition int.h:43
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:399
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition value_type.h:85
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:139
#define FL_UNSET
Old name of RB_FL_UNSET.
Definition fl_type.h:141
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:651
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:138
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:400
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.
Definition error.c:421
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition error.c:3148
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.
Definition error.c:363
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition error.c:794
void rb_name_error(ID id, const char *fmt,...)
Raises an instance of rb_eNameError.
Definition error.c:1784
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1091
void rb_name_error_str(VALUE str, const char *fmt,...)
Identical to rb_name_error(), except it takes a VALUE instead of ID.
Definition error.c:1799
VALUE rb_eNameError
NameError exception.
Definition error.c:1096
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1089
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.
Definition error.c:1058
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
Definition error.c:411
VALUE rb_eArgError
ArgumentError exception.
Definition error.c:1092
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition eval.c:993
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:442
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition error.h:48
VALUE rb_cObject
Documented in include/ruby/internal/globals.h.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:84
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:190
VALUE rb_cModule
Module class.
Definition object.c:53
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
Definition object.c:180
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition rgengc.h:232
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition rgengc.h:220
Encoding relates APIs.
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.
Definition symbol.c:1180
#define rb_check_frozen
Just another name of rb_check_frozen.
Definition error.h:264
#define rb_check_frozen_internal(obj)
Definition error.h:247
#define st_foreach_safe
Just another name of rb_st_foreach_safe.
Definition hash.h:51
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...
Definition load.c:643
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
Definition vm.c:1662
int rb_is_instance_id(ID id)
Classifies the given ID, then sees if it is an instance variable.
Definition symbol.c:1048
int rb_is_const_id(ID id)
Classifies the given ID, then sees if it is a constant.
Definition symbol.c:1030
int rb_is_class_id(ID id)
Classifies the given ID, then sees if it is a class variable.
Definition symbol.c:1036
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
Definition proc.c:848
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition string.c:3323
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...
Definition string.c:2825
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition string.c:1382
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition string.c:1834
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1514
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
Definition symbol.c:844
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.
Definition variable.c:3899
VALUE rb_obj_instance_variables(VALUE obj)
Resembles Object#instance_variables.
Definition variable.c:1909
VALUE rb_f_untrace_var(int argc, const VALUE *argv)
Deletes the passed tracer from the passed global variable, or if omitted, deletes everything.
Definition variable.c:670
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
Definition variable.c:2883
VALUE rb_const_list(void *)
This is another mysterious API that comes with no documents at all.
Definition variable.c:3103
VALUE rb_path2class(const char *path)
Resolves a Q::W::E::R-style path string to the actual class it points.
Definition variable.c:301
VALUE rb_autoload_p(VALUE space, ID name)
Queries if an autoload is defined at a point.
Definition variable.c:2756
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition variable.c:1223
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
Definition variable.c:248
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.
Definition variable.c:1593
VALUE rb_mod_remove_const(VALUE space, VALUE name)
Resembles Module#remove_const.
Definition variable.c:2975
VALUE rb_class_path_cached(VALUE mod)
Just another name of rb_mod_name.
Definition variable.c:194
VALUE rb_f_trace_var(int argc, const VALUE *argv)
Traces a global variable.
Definition variable.c:624
void rb_cvar_set(VALUE klass, ID name, VALUE val)
Assigns a value to a class variable.
Definition variable.c:3664
VALUE rb_cvar_get(VALUE klass, ID name)
Obtains a value from a class variable.
Definition variable.c:3733
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv)
Resembles Module#constants.
Definition variable.c:3135
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front)
Identical to rb_cvar_get(), except it takes additional "front" pointer.
Definition variable.c:3718
VALUE rb_path_to_class(VALUE path)
Identical to rb_path2class(), except it accepts the path as Ruby's string instead of C's.
Definition variable.c:256
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.
Definition variable.c:1215
void rb_const_set(VALUE space, ID name, VALUE val)
Names a constant.
Definition variable.c:3333
VALUE rb_autoload_load(VALUE space, ID name)
Kicks the autoload procedure as if it was "touched".
Definition variable.c:2718
VALUE rb_mod_name(VALUE mod)
Queries the name of a module.
Definition variable.c:134
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
Definition variable.c:307
VALUE rb_const_get_at(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
Definition variable.c:2889
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.
Definition variable.c:228
void rb_alias_variable(ID dst, ID src)
Aliases a global variable.
Definition variable.c:856
void rb_define_class_variable(VALUE, const char *, VALUE)
Just another name of rb_cv_set.
Definition variable.c:3773
VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name)
Resembles Object#remove_instance_variable.
Definition variable.c:1964
void * rb_mod_const_of(VALUE, void *)
This is a variant of rb_mod_const_at().
Definition variable.c:3081
st_index_t rb_ivar_count(VALUE obj)
Number of instance variables defined on an object.
Definition variable.c:1825
void * rb_mod_const_at(VALUE, void *)
This API is mysterious.
Definition variable.c:3064
VALUE rb_const_remove(VALUE space, ID name)
Identical to rb_mod_remove_const(), except it takes the name as ID instead of VALUE.
Definition variable.c:2986
VALUE rb_const_get_from(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
Definition variable.c:2877
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
Definition variable.c:1610
VALUE rb_cv_get(VALUE klass, const char *name)
Identical to rb_cvar_get(), except it accepts C's string instead of ID.
Definition variable.c:3766
int rb_const_defined_at(VALUE space, ID name)
Identical to rb_const_defined(), except it doesn't look for parent classes.
Definition variable.c:3197
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.
Definition variable.c:3759
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv)
Resembles Module#class_variables.
Definition variable.c:3864
VALUE rb_f_global_variables(void)
Queries the list of global variables.
Definition variable.c:824
VALUE rb_cvar_defined(VALUE klass, ID name)
Queries if the given class has the given class variable.
Definition variable.c:3740
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
Definition variable.c:185
int rb_const_defined_from(VALUE space, ID name)
Identical to rb_const_defined(), except it returns false for private constants.
Definition variable.c:3185
int rb_const_defined(VALUE space, ID name)
Queries if the constant is defined at the namespace.
Definition variable.c:3191
void rb_free_generic_ivar(VALUE obj)
Frees the list of instance variables.
Definition variable.c:1062
const char * rb_sourcefile(void)
Resembles __FILE__.
Definition vm.c:1688
void rb_clear_constant_cache_for_id(ID id)
Clears the inline constant caches associated with a particular ID.
Definition vm_method.c:142
VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
This API is practically a variant of rb_proc_call_kw() now.
Definition vm_eval.c:1914
ID rb_intern2(const char *name, long len)
Identical to rb_intern(), except it additionally takes the length of the string.
Definition symbol.c:782
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition symbol.c:1084
ID rb_to_id(VALUE str)
Identical to rb_intern(), except it takes an instance of rb_cString.
Definition string.c:11849
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
Definition symbol.c:959
rb_gvar_setter_t rb_gvar_var_setter
Definition variable.h:119
rb_gvar_marker_t rb_gvar_var_marker
Definition variable.h:128
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
Definition variable.c:3439
VALUE rb_gv_get(const char *name)
Obtains a global variable.
Definition variable.c:782
void rb_define_variable(const char *name, VALUE *var)
"Shares" a global variable between Ruby and C.
Definition variable.c:595
void rb_gvar_marker_t(VALUE *var)
Type that represents a global variable marker function.
Definition variable.h:53
void rb_deprecate_constant(VALUE mod, const char *name)
Asserts that the given constant is deprecated.
Definition variable.c:3487
void rb_gvar_setter_t(VALUE val, ID id, VALUE *data)
Type that represents a global variable setter function.
Definition variable.h:46
rb_gvar_setter_t rb_gvar_val_setter
This is the setter function that backs global variables defined from a ruby script.
Definition variable.h:94
rb_gvar_marker_t rb_gvar_undef_marker
Definition variable.h:80
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...
Definition variable.c:601
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
Definition variable.h:135
rb_gvar_getter_t rb_gvar_undef_getter
Definition variable.h:62
VALUE rb_gv_set(const char *name, VALUE val)
Assigns to a global variable.
Definition variable.c:768
rb_gvar_marker_t rb_gvar_val_marker
This is the setter function that backs global variables defined from a ruby script.
Definition variable.h:101
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition variable.c:3427
VALUE rb_gvar_getter_t(ID id, VALUE *data)
Type that represents a global variable getter function.
Definition variable.h:37
VALUE rb_iv_get(VALUE obj, const char *name)
Obtains an instance variable.
Definition variable.c:3922
rb_gvar_setter_t rb_gvar_undef_setter
Definition variable.h:71
rb_gvar_getter_t rb_gvar_val_getter
This is the getter function that backs global variables defined from a ruby script.
Definition variable.h:87
VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
Assigns to an instance variable.
Definition variable.c:3933
rb_gvar_getter_t rb_gvar_var_getter
Definition variable.h:110
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
Definition ractor.h:249
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
Definition sprintf.c:1219
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:366
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:161
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.
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
Definition variable.c:1727
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
Definition rclass.h:44
#define DATA_PTR(obj)
Convenient getter macro.
Definition rdata.h:71
#define ROBJECT(obj)
Convenient casting macro.
Definition robject.h:43
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
Definition rtypeddata.h:441
#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...
Definition rtypeddata.h:489
const char * rb_class2name(VALUE klass)
Queries the name of the passed class.
Definition variable.c:313
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
Definition variable.c:322
#define RB_NO_KEYWORDS
Do not pass keywords.
Definition scan_args.h:69
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
C99 shim for <stdbool.h>
Definition constant.h:33
Definition class.h:29
Definition variable.c:345
Definition st.h:79
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
Definition value_type.h:224