* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / variable.c
blob8cb507628c2de023bbbc0eb8d22c589b52b90833
1 /**********************************************************************
3 variable.c -
5 $Author$
6 created at: Tue Apr 19 23:55:15 JST 1994
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
12 **********************************************************************/
14 #include "ruby/internal/config.h"
15 #include <stddef.h>
16 #include "ruby/internal/stdbool.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 "variable.h"
38 #include "vm_core.h"
39 #include "ractor_core.h"
40 #include "vm_sync.h"
42 RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
43 #define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
45 typedef void rb_gvar_compact_t(void *var);
47 static struct rb_id_table *rb_global_tbl;
48 static ID autoload, classpath, tmp_classpath;
49 static VALUE autoload_featuremap; /* feature => autoload_i */
51 static void check_before_mod_set(VALUE, ID, VALUE, const char *);
52 static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
53 static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
54 static st_table *generic_iv_tbl_;
56 struct ivar_update {
57 union {
58 st_table *iv_index_tbl;
59 struct gen_ivtbl *ivtbl;
60 } u;
61 st_data_t index;
62 int iv_extended;
65 void
66 Init_var_tables(void)
68 rb_global_tbl = rb_id_table_create(0);
69 generic_iv_tbl_ = st_init_numtable();
70 autoload = rb_intern_const("__autoload__");
71 /* __classpath__: fully qualified class path */
72 classpath = rb_intern_const("__classpath__");
73 /* __tmp_classpath__: temporary class path which contains anonymous names */
74 tmp_classpath = rb_intern_const("__tmp_classpath__");
77 static inline bool
78 rb_namespace_p(VALUE obj)
80 if (RB_SPECIAL_CONST_P(obj)) return false;
81 switch (RB_BUILTIN_TYPE(obj)) {
82 case T_MODULE: case T_CLASS: return true;
83 default: break;
85 return false;
88 /**
89 * Returns +classpath+ of _klass_, if it is named, or +nil+ for
90 * anonymous +class+/+module+. A named +classpath+ may contain
91 * an anonymous component, but the last component is guaranteed
92 * to not be anonymous. <code>*permanent</code> is set to 1
93 * if +classpath+ has no anonymous components. There is no builtin
94 * Ruby level APIs that can change a permanent +classpath+.
96 static VALUE
97 classname(VALUE klass, int *permanent)
99 st_table *ivtbl;
100 st_data_t n;
102 *permanent = 0;
103 if (!RCLASS_EXT(klass)) return Qnil;
104 if (!(ivtbl = RCLASS_IV_TBL(klass))) return Qnil;
105 if (st_lookup(ivtbl, (st_data_t)classpath, &n)) {
106 *permanent = 1;
107 return (VALUE)n;
109 if (st_lookup(ivtbl, (st_data_t)tmp_classpath, &n)) return (VALUE)n;
110 return Qnil;
114 * call-seq:
115 * mod.name -> string
117 * Returns the name of the module <i>mod</i>. Returns nil for anonymous modules.
120 VALUE
121 rb_mod_name(VALUE mod)
123 int permanent;
124 return classname(mod, &permanent);
127 static VALUE
128 make_temporary_path(VALUE obj, VALUE klass)
130 VALUE path;
131 switch (klass) {
132 case Qnil:
133 path = rb_sprintf("#<Class:%p>", (void*)obj);
134 break;
135 case Qfalse:
136 path = rb_sprintf("#<Module:%p>", (void*)obj);
137 break;
138 default:
139 path = rb_sprintf("#<%"PRIsVALUE":%p>", klass, (void*)obj);
140 break;
142 OBJ_FREEZE(path);
143 return path;
146 typedef VALUE (*fallback_func)(VALUE obj, VALUE name);
148 static VALUE
149 rb_tmp_class_path(VALUE klass, int *permanent, fallback_func fallback)
151 VALUE path = classname(klass, permanent);
153 if (!NIL_P(path)) {
154 return path;
156 else {
157 if (RB_TYPE_P(klass, T_MODULE)) {
158 if (rb_obj_class(klass) == rb_cModule) {
159 path = Qfalse;
161 else {
162 int perm;
163 path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, fallback);
166 *permanent = 0;
167 return fallback(klass, path);
171 VALUE
172 rb_class_path(VALUE klass)
174 int permanent;
175 VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
176 if (!NIL_P(path)) path = rb_str_dup(path);
177 return path;
180 VALUE
181 rb_class_path_cached(VALUE klass)
183 return rb_mod_name(klass);
186 static VALUE
187 no_fallback(VALUE obj, VALUE name)
189 return name;
192 VALUE
193 rb_search_class_path(VALUE klass)
195 int permanent;
196 return rb_tmp_class_path(klass, &permanent, no_fallback);
199 static VALUE
200 build_const_pathname(VALUE head, VALUE tail)
202 VALUE path = rb_str_dup(head);
203 rb_str_cat2(path, "::");
204 rb_str_append(path, tail);
205 return rb_fstring(path);
208 static VALUE
209 build_const_path(VALUE head, ID tail)
211 return build_const_pathname(head, rb_id2str(tail));
214 void
215 rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
217 VALUE str;
218 ID pathid = classpath;
220 if (under == rb_cObject) {
221 str = rb_str_new_frozen(name);
223 else {
224 int permanent;
225 str = rb_tmp_class_path(under, &permanent, make_temporary_path);
226 str = build_const_pathname(str, name);
227 if (!permanent) {
228 pathid = tmp_classpath;
231 rb_ivar_set(klass, pathid, str);
234 void
235 rb_set_class_path(VALUE klass, VALUE under, const char *name)
237 VALUE str = rb_str_new2(name);
238 OBJ_FREEZE(str);
239 rb_set_class_path_string(klass, under, str);
242 VALUE
243 rb_path_to_class(VALUE pathname)
245 rb_encoding *enc = rb_enc_get(pathname);
246 const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
247 ID id;
248 VALUE c = rb_cObject;
250 if (!rb_enc_asciicompat(enc)) {
251 rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
253 pbeg = p = path;
254 pend = path + RSTRING_LEN(pathname);
255 if (path == pend || path[0] == '#') {
256 rb_raise(rb_eArgError, "can't retrieve anonymous class %"PRIsVALUE,
257 QUOTE(pathname));
259 while (p < pend) {
260 while (p < pend && *p != ':') p++;
261 id = rb_check_id_cstr(pbeg, p-pbeg, enc);
262 if (p < pend && p[0] == ':') {
263 if ((size_t)(pend - p) < 2 || p[1] != ':') goto undefined_class;
264 p += 2;
265 pbeg = p;
267 if (!id) {
268 goto undefined_class;
270 c = rb_const_search(c, id, TRUE, FALSE, FALSE);
271 if (c == Qundef) goto undefined_class;
272 if (!rb_namespace_p(c)) {
273 rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
274 pathname);
277 RB_GC_GUARD(pathname);
279 return c;
281 undefined_class:
282 rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE,
283 rb_str_subseq(pathname, 0, p-path));
284 UNREACHABLE_RETURN(Qundef);
287 VALUE
288 rb_path2class(const char *path)
290 return rb_path_to_class(rb_str_new_cstr(path));
293 VALUE
294 rb_class_name(VALUE klass)
296 return rb_class_path(rb_class_real(klass));
299 const char *
300 rb_class2name(VALUE klass)
302 int permanent;
303 VALUE path = rb_tmp_class_path(rb_class_real(klass), &permanent, make_temporary_path);
304 if (NIL_P(path)) return NULL;
305 return RSTRING_PTR(path);
308 const char *
309 rb_obj_classname(VALUE obj)
311 return rb_class2name(CLASS_OF(obj));
314 struct trace_var {
315 int removed;
316 void (*func)(VALUE arg, VALUE val);
317 VALUE data;
318 struct trace_var *next;
321 struct rb_global_variable {
322 int counter;
323 int block_trace;
324 VALUE *data;
325 rb_gvar_getter_t *getter;
326 rb_gvar_setter_t *setter;
327 rb_gvar_marker_t *marker;
328 rb_gvar_compact_t *compactor;
329 struct trace_var *trace;
332 struct rb_global_entry {
333 struct rb_global_variable *var;
334 ID id;
335 bool ractor_local;
338 static struct rb_global_entry*
339 rb_find_global_entry(ID id)
341 struct rb_global_entry *entry;
342 VALUE data;
344 if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
345 entry = NULL;
347 else {
348 entry = (struct rb_global_entry *)data;
349 RUBY_ASSERT(entry != NULL);
352 if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
353 rb_raise(rb_eRactorIsolationError, "can not access global variables %s from non-main Ractors", rb_id2name(id));
356 return entry;
359 void
360 rb_gvar_ractor_local(const char *name)
362 struct rb_global_entry *entry = rb_find_global_entry(rb_intern(name));
363 entry->ractor_local = true;
366 static void
367 rb_gvar_undef_compactor(void *var)
371 static struct rb_global_entry*
372 rb_global_entry(ID id)
374 struct rb_global_entry *entry = rb_find_global_entry(id);
375 if (!entry) {
376 struct rb_global_variable *var;
377 entry = ALLOC(struct rb_global_entry);
378 var = ALLOC(struct rb_global_variable);
379 entry->id = id;
380 entry->var = var;
381 entry->ractor_local = false;
382 var->counter = 1;
383 var->data = 0;
384 var->getter = rb_gvar_undef_getter;
385 var->setter = rb_gvar_undef_setter;
386 var->marker = rb_gvar_undef_marker;
387 var->compactor = rb_gvar_undef_compactor;
389 var->block_trace = 0;
390 var->trace = 0;
391 rb_id_table_insert(rb_global_tbl, id, (VALUE)entry);
393 return entry;
396 VALUE
397 rb_gvar_undef_getter(ID id, VALUE *_)
399 rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id));
401 return Qnil;
404 static void
405 rb_gvar_val_compactor(void *_var)
407 struct rb_global_variable *var = (struct rb_global_variable *)_var;
409 VALUE obj = (VALUE)var->data;
411 if (obj) {
412 VALUE new = rb_gc_location(obj);
413 if (new != obj) {
414 var->data = (void*)new;
419 void
420 rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
422 struct rb_global_variable *var = rb_global_entry(id)->var;
423 var->getter = rb_gvar_val_getter;
424 var->setter = rb_gvar_val_setter;
425 var->marker = rb_gvar_val_marker;
426 var->compactor = rb_gvar_val_compactor;
428 var->data = (void*)val;
431 void
432 rb_gvar_undef_marker(VALUE *var)
436 VALUE
437 rb_gvar_val_getter(ID id, VALUE *data)
439 return (VALUE)data;
442 void
443 rb_gvar_val_setter(VALUE val, ID id, VALUE *_)
445 struct rb_global_variable *var = rb_global_entry(id)->var;
446 var->data = (void*)val;
449 void
450 rb_gvar_val_marker(VALUE *var)
452 VALUE data = (VALUE)var;
453 if (data) rb_gc_mark_movable(data);
456 VALUE
457 rb_gvar_var_getter(ID id, VALUE *var)
459 if (!var) return Qnil;
460 return *var;
463 void
464 rb_gvar_var_setter(VALUE val, ID id, VALUE *data)
466 *data = val;
469 void
470 rb_gvar_var_marker(VALUE *var)
472 if (var) rb_gc_mark_maybe(*var);
475 void
476 rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
478 rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id));
481 static enum rb_id_table_iterator_result
482 mark_global_entry(VALUE v, void *ignored)
484 struct rb_global_entry *entry = (struct rb_global_entry *)v;
485 struct trace_var *trace;
486 struct rb_global_variable *var = entry->var;
488 (*var->marker)(var->data);
489 trace = var->trace;
490 while (trace) {
491 if (trace->data) rb_gc_mark_maybe(trace->data);
492 trace = trace->next;
494 return ID_TABLE_CONTINUE;
497 void
498 rb_gc_mark_global_tbl(void)
500 if (rb_global_tbl) {
501 rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
505 static enum rb_id_table_iterator_result
506 update_global_entry(VALUE v, void *ignored)
508 struct rb_global_entry *entry = (struct rb_global_entry *)v;
509 struct rb_global_variable *var = entry->var;
511 (*var->compactor)(var);
512 return ID_TABLE_CONTINUE;
515 void
516 rb_gc_update_global_tbl(void)
518 if (rb_global_tbl) {
519 rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
523 static ID
524 global_id(const char *name)
526 ID id;
528 if (name[0] == '$') id = rb_intern(name);
529 else {
530 size_t len = strlen(name);
531 VALUE vbuf = 0;
532 char *buf = ALLOCV_N(char, vbuf, len+1);
533 buf[0] = '$';
534 memcpy(buf+1, name, len);
535 id = rb_intern2(buf, len+1);
536 ALLOCV_END(vbuf);
538 return id;
541 static ID
542 find_global_id(const char *name)
544 ID id;
545 size_t len = strlen(name);
547 if (name[0] == '$') {
548 id = rb_check_id_cstr(name, len, NULL);
550 else {
551 VALUE vbuf = 0;
552 char *buf = ALLOCV_N(char, vbuf, len+1);
553 buf[0] = '$';
554 memcpy(buf+1, name, len);
555 id = rb_check_id_cstr(buf, len+1, NULL);
556 ALLOCV_END(vbuf);
559 return id;
562 void
563 rb_define_hooked_variable(
564 const char *name,
565 VALUE *var,
566 rb_gvar_getter_t *getter,
567 rb_gvar_setter_t *setter)
569 volatile VALUE tmp = var ? *var : Qnil;
570 ID id = global_id(name);
571 struct rb_global_variable *gvar = rb_global_entry(id)->var;
573 gvar->data = (void*)var;
574 gvar->getter = getter ? (rb_gvar_getter_t *)getter : rb_gvar_var_getter;
575 gvar->setter = setter ? (rb_gvar_setter_t *)setter : rb_gvar_var_setter;
576 gvar->marker = rb_gvar_var_marker;
578 RB_GC_GUARD(tmp);
581 void
582 rb_define_variable(const char *name, VALUE *var)
584 rb_define_hooked_variable(name, var, 0, 0);
587 void
588 rb_define_readonly_variable(const char *name, const VALUE *var)
590 rb_define_hooked_variable(name, (VALUE *)var, 0, rb_gvar_readonly_setter);
593 void
594 rb_define_virtual_variable(
595 const char *name,
596 rb_gvar_getter_t *getter,
597 rb_gvar_setter_t *setter)
599 if (!getter) getter = rb_gvar_val_getter;
600 if (!setter) setter = rb_gvar_readonly_setter;
601 rb_define_hooked_variable(name, 0, getter, setter);
604 static void
605 rb_trace_eval(VALUE cmd, VALUE val)
607 rb_eval_cmd_kw(cmd, rb_ary_new3(1, val), RB_NO_KEYWORDS);
610 VALUE
611 rb_f_trace_var(int argc, const VALUE *argv)
613 VALUE var, cmd;
614 struct rb_global_entry *entry;
615 struct trace_var *trace;
617 if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
618 cmd = rb_block_proc();
620 if (NIL_P(cmd)) {
621 return rb_f_untrace_var(argc, argv);
623 entry = rb_global_entry(rb_to_id(var));
624 trace = ALLOC(struct trace_var);
625 trace->next = entry->var->trace;
626 trace->func = rb_trace_eval;
627 trace->data = cmd;
628 trace->removed = 0;
629 entry->var->trace = trace;
631 return Qnil;
634 static void
635 remove_trace(struct rb_global_variable *var)
637 struct trace_var *trace = var->trace;
638 struct trace_var t;
639 struct trace_var *next;
641 t.next = trace;
642 trace = &t;
643 while (trace->next) {
644 next = trace->next;
645 if (next->removed) {
646 trace->next = next->next;
647 xfree(next);
649 else {
650 trace = next;
653 var->trace = t.next;
656 VALUE
657 rb_f_untrace_var(int argc, const VALUE *argv)
659 VALUE var, cmd;
660 ID id;
661 struct rb_global_entry *entry;
662 struct trace_var *trace;
664 rb_scan_args(argc, argv, "11", &var, &cmd);
665 id = rb_check_id(&var);
666 if (!id) {
667 rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
669 if ((entry = rb_find_global_entry(id)) == NULL) {
670 rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
673 trace = entry->var->trace;
674 if (NIL_P(cmd)) {
675 VALUE ary = rb_ary_new();
677 while (trace) {
678 struct trace_var *next = trace->next;
679 rb_ary_push(ary, (VALUE)trace->data);
680 trace->removed = 1;
681 trace = next;
684 if (!entry->var->block_trace) remove_trace(entry->var);
685 return ary;
687 else {
688 while (trace) {
689 if (trace->data == cmd) {
690 trace->removed = 1;
691 if (!entry->var->block_trace) remove_trace(entry->var);
692 return rb_ary_new3(1, cmd);
694 trace = trace->next;
697 return Qnil;
700 struct trace_data {
701 struct trace_var *trace;
702 VALUE val;
705 static VALUE
706 trace_ev(VALUE v)
708 struct trace_data *data = (void *)v;
709 struct trace_var *trace = data->trace;
711 while (trace) {
712 (*trace->func)(trace->data, data->val);
713 trace = trace->next;
716 return Qnil;
719 static VALUE
720 trace_en(VALUE v)
722 struct rb_global_variable *var = (void *)v;
723 var->block_trace = 0;
724 remove_trace(var);
725 return Qnil; /* not reached */
728 static VALUE
729 rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val)
731 struct trace_data trace;
732 struct rb_global_variable *var = entry->var;
734 (*var->setter)(val, entry->id, var->data);
736 if (var->trace && !var->block_trace) {
737 var->block_trace = 1;
738 trace.trace = var->trace;
739 trace.val = val;
740 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
742 return val;
745 VALUE
746 rb_gvar_set(ID id, VALUE val)
748 struct rb_global_entry *entry;
749 entry = rb_global_entry(id);
751 return rb_gvar_set_entry(entry, val);
754 VALUE
755 rb_gv_set(const char *name, VALUE val)
757 return rb_gvar_set(global_id(name), val);
760 VALUE
761 rb_gvar_get(ID id)
763 struct rb_global_entry *entry = rb_global_entry(id);
764 struct rb_global_variable *var = entry->var;
765 return (*var->getter)(entry->id, var->data);
768 VALUE
769 rb_gv_get(const char *name)
771 ID id = find_global_id(name);
773 if (!id) {
774 rb_warning("global variable `%s' not initialized", name);
775 return Qnil;
778 return rb_gvar_get(id);
781 MJIT_FUNC_EXPORTED VALUE
782 rb_gvar_defined(ID id)
784 struct rb_global_entry *entry = rb_global_entry(id);
785 return RBOOL(entry->var->getter != rb_gvar_undef_getter);
788 rb_gvar_getter_t *
789 rb_gvar_getter_function_of(ID id)
791 const struct rb_global_entry *entry = rb_global_entry(id);
792 return entry->var->getter;
795 rb_gvar_setter_t *
796 rb_gvar_setter_function_of(ID id)
798 const struct rb_global_entry *entry = rb_global_entry(id);
799 return entry->var->setter;
802 static enum rb_id_table_iterator_result
803 gvar_i(ID key, VALUE val, void *a)
805 VALUE ary = (VALUE)a;
806 rb_ary_push(ary, ID2SYM(key));
807 return ID_TABLE_CONTINUE;
810 VALUE
811 rb_f_global_variables(void)
813 VALUE ary = rb_ary_new();
814 VALUE sym, backref = rb_backref_get();
816 if (!rb_ractor_main_p()) {
817 rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
820 rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary);
821 if (!NIL_P(backref)) {
822 char buf[2];
823 int i, nmatch = rb_match_count(backref);
824 buf[0] = '$';
825 for (i = 1; i <= nmatch; ++i) {
826 if (!rb_match_nth_defined(i, backref)) continue;
827 if (i < 10) {
828 /* probably reused, make static ID */
829 buf[1] = (char)(i + '0');
830 sym = ID2SYM(rb_intern2(buf, 2));
832 else {
833 /* dynamic symbol */
834 sym = rb_str_intern(rb_sprintf("$%d", i));
836 rb_ary_push(ary, sym);
839 return ary;
842 void
843 rb_alias_variable(ID name1, ID name2)
845 struct rb_global_entry *entry1, *entry2;
846 VALUE data1;
847 struct rb_id_table *gtbl = rb_global_tbl;
849 if (!rb_ractor_main_p()) {
850 rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
853 entry2 = rb_global_entry(name2);
854 if (!rb_id_table_lookup(gtbl, name1, &data1)) {
855 entry1 = ALLOC(struct rb_global_entry);
856 entry1->id = name1;
857 rb_id_table_insert(gtbl, name1, (VALUE)entry1);
859 else if ((entry1 = (struct rb_global_entry *)data1)->var != entry2->var) {
860 struct rb_global_variable *var = entry1->var;
861 if (var->block_trace) {
862 rb_raise(rb_eRuntimeError, "can't alias in tracer");
864 var->counter--;
865 if (var->counter == 0) {
866 struct trace_var *trace = var->trace;
867 while (trace) {
868 struct trace_var *next = trace->next;
869 xfree(trace);
870 trace = next;
872 xfree(var);
875 else {
876 return;
878 entry2->var->counter++;
879 entry1->var = entry2->var;
882 static bool
883 iv_index_tbl_lookup(struct st_table *tbl, ID id, uint32_t *indexp)
885 st_data_t ent_data;
886 int r;
888 if (tbl == NULL) return false;
890 RB_VM_LOCK_ENTER();
892 r = st_lookup(tbl, (st_data_t)id, &ent_data);
894 RB_VM_LOCK_LEAVE();
896 if (r) {
897 struct rb_iv_index_tbl_entry *ent = (void *)ent_data;
898 *indexp = ent->index;
899 return true;
901 else {
902 return false;
906 static void
907 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
909 if (UNLIKELY(!rb_ractor_main_p())) {
910 if (rb_is_instance_id(id)) { // check only normal ivars
911 rb_raise(rb_eRactorIsolationError, "can not set instance variables of classes/modules by non-main Ractors");
916 #define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
917 if (UNLIKELY(!rb_ractor_main_p())) { \
918 rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
921 static inline struct st_table *
922 generic_ivtbl(VALUE obj, ID id, bool force_check_ractor)
924 ASSERT_vm_locking();
926 if ((force_check_ractor || LIKELY(rb_is_instance_id(id)) /* not internal ID */ ) &&
927 !RB_OBJ_FROZEN_RAW(obj) &&
928 UNLIKELY(!rb_ractor_main_p()) &&
929 UNLIKELY(rb_ractor_shareable_p(obj))) {
931 rb_raise(rb_eRactorIsolationError, "can not access instance variables of shareable objects from non-main Ractors");
933 return generic_iv_tbl_;
936 static inline struct st_table *
937 generic_ivtbl_no_ractor_check(VALUE obj)
939 return generic_ivtbl(obj, 0, false);
942 static int
943 gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
945 st_data_t data;
946 int r = 0;
948 RB_VM_LOCK_ENTER();
950 if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) {
951 *ivtbl = (struct gen_ivtbl *)data;
952 r = 1;
955 RB_VM_LOCK_LEAVE();
957 return r;
960 MJIT_FUNC_EXPORTED int
961 rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl)
963 return gen_ivtbl_get(obj, 0, ivtbl);
966 MJIT_FUNC_EXPORTED VALUE
967 rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index)
969 struct gen_ivtbl *ivtbl;
971 if (gen_ivtbl_get(obj, id, &ivtbl)) {
972 if (LIKELY(index < ivtbl->numiv)) {
973 VALUE val = ivtbl->ivptr[index];
974 return val;
978 return Qundef;
981 static VALUE
982 generic_ivar_delete(VALUE obj, ID id, VALUE undef)
984 struct gen_ivtbl *ivtbl;
986 if (gen_ivtbl_get(obj, id, &ivtbl)) {
987 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
988 uint32_t index;
990 if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
991 if (index < ivtbl->numiv) {
992 VALUE ret = ivtbl->ivptr[index];
994 ivtbl->ivptr[index] = Qundef;
995 return ret == Qundef ? undef : ret;
999 return undef;
1002 static VALUE
1003 generic_ivar_get(VALUE obj, ID id, VALUE undef)
1005 struct gen_ivtbl *ivtbl;
1007 if (gen_ivtbl_get(obj, id, &ivtbl)) {
1008 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1009 uint32_t index;
1011 if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
1012 if (index < ivtbl->numiv) {
1013 VALUE ret = ivtbl->ivptr[index];
1015 return ret == Qundef ? undef : ret;
1019 return undef;
1022 static size_t
1023 gen_ivtbl_bytes(size_t n)
1025 return offsetof(struct gen_ivtbl, ivptr) + n * sizeof(VALUE);
1028 static struct gen_ivtbl *
1029 gen_ivtbl_resize(struct gen_ivtbl *old, uint32_t n)
1031 uint32_t len = old ? old->numiv : 0;
1032 struct gen_ivtbl *ivtbl = xrealloc(old, gen_ivtbl_bytes(n));
1034 ivtbl->numiv = n;
1035 for (; len < n; len++) {
1036 ivtbl->ivptr[len] = Qundef;
1039 return ivtbl;
1042 #if 0
1043 static struct gen_ivtbl *
1044 gen_ivtbl_dup(const struct gen_ivtbl *orig)
1046 size_t s = gen_ivtbl_bytes(orig->numiv);
1047 struct gen_ivtbl *ivtbl = xmalloc(s);
1049 memcpy(ivtbl, orig, s);
1051 return ivtbl;
1053 #endif
1055 static uint32_t
1056 iv_index_tbl_newsize(struct ivar_update *ivup)
1058 if (!ivup->iv_extended) {
1059 return (uint32_t)ivup->u.iv_index_tbl->num_entries;
1061 else {
1062 uint32_t index = (uint32_t)ivup->index; /* should not overflow */
1063 return (index+1) + (index+1)/4; /* (index+1)*1.25 */
1067 static int
1068 generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
1070 ASSERT_vm_locking();
1072 struct ivar_update *ivup = (struct ivar_update *)u;
1073 struct gen_ivtbl *ivtbl = 0;
1075 if (existing) {
1076 ivtbl = (struct gen_ivtbl *)*v;
1077 if (ivup->index < ivtbl->numiv) {
1078 ivup->u.ivtbl = ivtbl;
1079 return ST_STOP;
1082 FL_SET((VALUE)*k, FL_EXIVAR);
1083 uint32_t newsize = iv_index_tbl_newsize(ivup);
1084 ivtbl = gen_ivtbl_resize(ivtbl, newsize);
1085 *v = (st_data_t)ivtbl;
1086 ivup->u.ivtbl = ivtbl;
1087 return ST_CONTINUE;
1090 static VALUE
1091 generic_ivar_defined(VALUE obj, ID id)
1093 struct gen_ivtbl *ivtbl;
1094 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1095 uint32_t index;
1097 if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return Qfalse;
1098 if (!gen_ivtbl_get(obj, id, &ivtbl)) return Qfalse;
1100 return RBOOL((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef));
1103 static int
1104 generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
1106 struct gen_ivtbl *ivtbl;
1107 uint32_t index;
1108 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1110 if (!iv_index_tbl) return 0;
1111 if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return 0;
1112 if (!gen_ivtbl_get(obj, id, &ivtbl)) return 0;
1114 if (index < ivtbl->numiv) {
1115 if (ivtbl->ivptr[index] != Qundef) {
1116 *valp = ivtbl->ivptr[index];
1117 ivtbl->ivptr[index] = Qundef;
1118 return 1;
1121 return 0;
1124 static void
1125 gen_ivtbl_mark(const struct gen_ivtbl *ivtbl)
1127 uint32_t i;
1129 for (i = 0; i < ivtbl->numiv; i++) {
1130 rb_gc_mark(ivtbl->ivptr[i]);
1134 void
1135 rb_mark_generic_ivar(VALUE obj)
1137 struct gen_ivtbl *ivtbl;
1139 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1140 gen_ivtbl_mark(ivtbl);
1144 void
1145 rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
1147 st_data_t key = (st_data_t)rsrc;
1148 st_data_t ivtbl;
1150 if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl))
1151 st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl);
1154 void
1155 rb_free_generic_ivar(VALUE obj)
1157 st_data_t key = (st_data_t)obj, ivtbl;
1159 if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, &ivtbl))
1160 xfree((struct gen_ivtbl *)ivtbl);
1163 RUBY_FUNC_EXPORTED size_t
1164 rb_generic_ivar_memsize(VALUE obj)
1166 struct gen_ivtbl *ivtbl;
1168 if (gen_ivtbl_get(obj, 0, &ivtbl))
1169 return gen_ivtbl_bytes(ivtbl->numiv);
1170 return 0;
1173 static size_t
1174 gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
1176 uint32_t i;
1177 size_t n = 0;
1179 for (i = 0; i < ivtbl->numiv; i++) {
1180 if (ivtbl->ivptr[i] != Qundef) {
1181 n++;
1185 return n;
1188 static int
1189 lock_st_lookup(st_table *tab, st_data_t key, st_data_t *value)
1191 int r;
1192 RB_VM_LOCK_ENTER();
1194 r = st_lookup(tab, key, value);
1196 RB_VM_LOCK_LEAVE();
1197 return r;
1200 static int
1201 lock_st_delete(st_table *tab, st_data_t *key, st_data_t *value)
1203 int r;
1204 RB_VM_LOCK_ENTER();
1206 r = st_delete(tab, key, value);
1208 RB_VM_LOCK_LEAVE();
1209 return r;
1212 static int
1213 lock_st_is_member(st_table *tab, st_data_t key)
1215 int r;
1216 RB_VM_LOCK_ENTER();
1218 r = st_is_member(tab, key);
1220 RB_VM_LOCK_LEAVE();
1221 return r;
1224 static int
1225 lock_st_insert(st_table *tab, st_data_t key, st_data_t value)
1227 int r;
1228 RB_VM_LOCK_ENTER();
1230 r = st_insert(tab, key, value);
1232 RB_VM_LOCK_LEAVE();
1233 return r;
1236 VALUE
1237 rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
1239 if (SPECIAL_CONST_P(obj)) return undef;
1240 switch (BUILTIN_TYPE(obj)) {
1241 case T_OBJECT:
1243 uint32_t index;
1244 uint32_t len = ROBJECT_NUMIV(obj);
1245 VALUE *ptr = ROBJECT_IVPTR(obj);
1246 VALUE val;
1248 if (iv_index_tbl_lookup(ROBJECT_IV_INDEX_TBL(obj), id, &index) &&
1249 index < len &&
1250 (val = ptr[index]) != Qundef) {
1251 return val;
1253 else {
1254 break;
1257 case T_CLASS:
1258 case T_MODULE:
1260 st_data_t val;
1262 if (RCLASS_IV_TBL(obj) &&
1263 lock_st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) {
1264 if (rb_is_instance_id(id) &&
1265 UNLIKELY(!rb_ractor_main_p()) &&
1266 !rb_ractor_shareable_p(val)) {
1267 rb_raise(rb_eRactorIsolationError,
1268 "can not get unshareable values from instance variables of classes/modules from non-main Ractors");
1270 return val;
1272 else {
1273 break;
1276 default:
1277 if (FL_TEST(obj, FL_EXIVAR))
1278 return generic_ivar_get(obj, id, undef);
1279 break;
1281 return undef;
1284 VALUE
1285 rb_ivar_get(VALUE obj, ID id)
1287 VALUE iv = rb_ivar_lookup(obj, id, Qnil);
1288 RB_DEBUG_COUNTER_INC(ivar_get_base);
1289 return iv;
1292 VALUE
1293 rb_attr_get(VALUE obj, ID id)
1295 return rb_ivar_lookup(obj, id, Qnil);
1298 static VALUE
1299 rb_ivar_delete(VALUE obj, ID id, VALUE undef)
1301 VALUE *ptr;
1302 struct st_table *iv_index_tbl;
1303 uint32_t len, index;
1305 rb_check_frozen(obj);
1306 switch (BUILTIN_TYPE(obj)) {
1307 case T_OBJECT:
1308 len = ROBJECT_NUMIV(obj);
1309 ptr = ROBJECT_IVPTR(obj);
1310 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1311 if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
1312 index < len) {
1313 VALUE val = ptr[index];
1314 ptr[index] = Qundef;
1316 if (val != Qundef) {
1317 return val;
1320 break;
1321 case T_CLASS:
1322 case T_MODULE:
1323 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1324 if (RCLASS_IV_TBL(obj)) {
1325 st_data_t id_data = (st_data_t)id, val;
1326 if (lock_st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) {
1327 return (VALUE)val;
1330 break;
1331 default:
1332 if (FL_TEST(obj, FL_EXIVAR))
1333 return generic_ivar_delete(obj, id, undef);
1334 break;
1336 return undef;
1339 VALUE
1340 rb_attr_delete(VALUE obj, ID id)
1342 return rb_ivar_delete(obj, id, Qnil);
1345 static st_table *
1346 iv_index_tbl_make(VALUE obj, VALUE klass)
1348 st_table *iv_index_tbl;
1350 if (UNLIKELY(!klass)) {
1351 rb_raise(rb_eTypeError, "hidden object cannot have instance variables");
1354 if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
1355 RB_VM_LOCK_ENTER();
1356 if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
1357 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
1359 RB_VM_LOCK_LEAVE();
1362 return iv_index_tbl;
1365 static void
1366 iv_index_tbl_extend(struct ivar_update *ivup, ID id, VALUE klass)
1368 ASSERT_vm_locking();
1369 st_data_t ent_data;
1370 struct rb_iv_index_tbl_entry *ent;
1372 if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ent_data)) {
1373 ent = (void *)ent_data;
1374 ivup->index = ent->index;
1375 return;
1377 if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) {
1378 rb_raise(rb_eArgError, "too many instance variables");
1380 ent = ALLOC(struct rb_iv_index_tbl_entry);
1381 ent->index = ivup->index = (uint32_t)ivup->u.iv_index_tbl->num_entries;
1382 ent->class_value = klass;
1383 ent->class_serial = RCLASS_SERIAL(klass);
1384 st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, (st_data_t)ent);
1385 ivup->iv_extended = 1;
1388 static void
1389 generic_ivar_set(VALUE obj, ID id, VALUE val)
1391 VALUE klass = rb_obj_class(obj);
1392 struct ivar_update ivup;
1393 ivup.iv_extended = 0;
1394 ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
1396 RB_VM_LOCK_ENTER();
1398 iv_index_tbl_extend(&ivup, id, klass);
1399 st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update,
1400 (st_data_t)&ivup);
1402 RB_VM_LOCK_LEAVE();
1404 ivup.u.ivtbl->ivptr[ivup.index] = val;
1406 RB_OBJ_WRITTEN(obj, Qundef, val);
1409 static VALUE *
1410 obj_ivar_heap_alloc(VALUE obj, size_t newsize)
1412 VALUE *newptr = rb_transient_heap_alloc(obj, sizeof(VALUE) * newsize);
1414 if (newptr != NULL) {
1415 ROBJ_TRANSIENT_SET(obj);
1417 else {
1418 ROBJ_TRANSIENT_UNSET(obj);
1419 newptr = ALLOC_N(VALUE, newsize);
1421 return newptr;
1424 static VALUE *
1425 obj_ivar_heap_realloc(VALUE obj, int32_t len, size_t newsize)
1427 VALUE *newptr;
1428 int i;
1430 if (ROBJ_TRANSIENT_P(obj)) {
1431 const VALUE *orig_ptr = ROBJECT(obj)->as.heap.ivptr;
1432 newptr = obj_ivar_heap_alloc(obj, newsize);
1434 assert(newptr);
1435 ROBJECT(obj)->as.heap.ivptr = newptr;
1436 for (i=0; i<(int)len; i++) {
1437 newptr[i] = orig_ptr[i];
1440 else {
1441 REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize);
1442 newptr = ROBJECT(obj)->as.heap.ivptr;
1445 return newptr;
1448 #if USE_TRANSIENT_HEAP
1449 void
1450 rb_obj_transient_heap_evacuate(VALUE obj, int promote)
1452 if (ROBJ_TRANSIENT_P(obj)) {
1453 uint32_t len = ROBJECT_NUMIV(obj);
1454 const VALUE *old_ptr = ROBJECT_IVPTR(obj);
1455 VALUE *new_ptr;
1457 if (promote) {
1458 new_ptr = ALLOC_N(VALUE, len);
1459 ROBJ_TRANSIENT_UNSET(obj);
1461 else {
1462 new_ptr = obj_ivar_heap_alloc(obj, len);
1464 MEMCPY(new_ptr, old_ptr, VALUE, len);
1465 ROBJECT(obj)->as.heap.ivptr = new_ptr;
1468 #endif
1470 static void
1471 init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table *index_tbl)
1473 VALUE *ptr = ROBJECT_IVPTR(obj);
1474 VALUE *newptr;
1476 if (RBASIC(obj)->flags & ROBJECT_EMBED) {
1477 newptr = obj_ivar_heap_alloc(obj, newsize);
1478 MEMCPY(newptr, ptr, VALUE, len);
1479 RBASIC(obj)->flags &= ~ROBJECT_EMBED;
1480 ROBJECT(obj)->as.heap.ivptr = newptr;
1482 else {
1483 newptr = obj_ivar_heap_realloc(obj, len, newsize);
1486 for (; len < newsize; len++) {
1487 newptr[len] = Qundef;
1489 ROBJECT(obj)->as.heap.numiv = newsize;
1490 ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
1493 void
1494 rb_init_iv_list(VALUE obj)
1496 st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1497 uint32_t newsize = (uint32_t)index_tbl->num_entries;
1498 uint32_t len = ROBJECT_NUMIV(obj);
1499 init_iv_list(obj, len, newsize, index_tbl);
1502 // Retrieve or create the id-to-index mapping for a given object and an
1503 // instance variable name.
1504 static struct ivar_update
1505 obj_ensure_iv_index_mapping(VALUE obj, ID id)
1507 VALUE klass = rb_obj_class(obj);
1508 struct ivar_update ivup;
1509 ivup.iv_extended = 0;
1510 ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
1512 RB_VM_LOCK_ENTER();
1514 iv_index_tbl_extend(&ivup, id, klass);
1516 RB_VM_LOCK_LEAVE();
1518 return ivup;
1521 // Return the instance variable index for a given name and T_OBJECT object. The
1522 // mapping between name and index lives on `rb_obj_class(obj)` and is created
1523 // if not already present.
1525 // @note May raise when there are too many instance variables.
1526 // @note YJIT uses this function at compile time to simplify the work needed to
1527 // access the variable at runtime.
1528 uint32_t
1529 rb_obj_ensure_iv_index_mapping(VALUE obj, ID id)
1531 RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
1532 // This uint32_t cast shouldn't lose information as it's checked in
1533 // iv_index_tbl_extend(). The index is stored as an uint32_t in
1534 // struct rb_iv_index_tbl_entry.
1535 return (uint32_t)obj_ensure_iv_index_mapping(obj, id).index;
1538 static VALUE
1539 obj_ivar_set(VALUE obj, ID id, VALUE val)
1541 uint32_t len;
1542 struct ivar_update ivup = obj_ensure_iv_index_mapping(obj, id);
1544 len = ROBJECT_NUMIV(obj);
1545 if (len <= ivup.index) {
1546 uint32_t newsize = iv_index_tbl_newsize(&ivup);
1547 init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
1549 RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
1551 return val;
1554 static void
1555 ivar_set(VALUE obj, ID id, VALUE val)
1557 RB_DEBUG_COUNTER_INC(ivar_set_base);
1559 switch (BUILTIN_TYPE(obj)) {
1560 case T_OBJECT:
1561 obj_ivar_set(obj, id, val);
1562 break;
1563 case T_CLASS:
1564 case T_MODULE:
1565 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1566 rb_class_ivar_set(obj, id, val);
1567 break;
1568 default:
1569 generic_ivar_set(obj, id, val);
1570 break;
1574 VALUE
1575 rb_ivar_set(VALUE obj, ID id, VALUE val)
1577 rb_check_frozen(obj);
1578 ivar_set(obj, id, val);
1579 return val;
1582 void
1583 rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
1585 // should be internal instance variable name (no @ prefix)
1586 VM_ASSERT(!rb_is_instance_id(id));
1588 ivar_set(obj, id, val);
1591 VALUE
1592 rb_ivar_defined(VALUE obj, ID id)
1594 VALUE val;
1595 struct st_table *iv_index_tbl;
1596 uint32_t index;
1598 if (SPECIAL_CONST_P(obj)) return Qfalse;
1599 switch (BUILTIN_TYPE(obj)) {
1600 case T_OBJECT:
1601 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1602 if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
1603 index < ROBJECT_NUMIV(obj) &&
1604 (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
1605 return Qtrue;
1607 break;
1608 case T_CLASS:
1609 case T_MODULE:
1610 if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
1611 return Qtrue;
1612 break;
1613 default:
1614 if (FL_TEST(obj, FL_EXIVAR))
1615 return generic_ivar_defined(obj, id);
1616 break;
1618 return Qfalse;
1621 typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
1622 st_data_t rb_st_nth_key(st_table *tab, st_index_t index);
1624 static ID
1625 iv_index_tbl_nth_id(st_table *iv_index_tbl, uint32_t index)
1627 st_data_t key;
1628 RB_VM_LOCK_ENTER();
1630 key = rb_st_nth_key(iv_index_tbl, index);
1632 RB_VM_LOCK_LEAVE();
1633 return (ID)key;
1636 static inline bool
1637 ivar_each_i(st_table *iv_index_tbl, VALUE val, uint32_t i, rb_ivar_foreach_callback_func *func, st_data_t arg)
1639 if (val != Qundef) {
1640 ID id = iv_index_tbl_nth_id(iv_index_tbl, i);
1641 switch (func(id, val, arg)) {
1642 case ST_CHECK:
1643 case ST_CONTINUE:
1644 break;
1645 case ST_STOP:
1646 return true;
1647 default:
1648 rb_bug("unreachable");
1651 return false;
1654 static void
1655 obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1657 st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1658 if (!iv_index_tbl) return;
1659 uint32_t i=0;
1661 for (i=0; i < ROBJECT_NUMIV(obj); i++) {
1662 VALUE val = ROBJECT_IVPTR(obj)[i];
1663 if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
1664 return;
1669 static void
1670 gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1672 struct gen_ivtbl *ivtbl;
1673 st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1674 if (!iv_index_tbl) return;
1675 if (!gen_ivtbl_get(obj, 0, &ivtbl)) return;
1677 for (uint32_t i=0; i<ivtbl->numiv; i++) {
1678 VALUE val = ivtbl->ivptr[i];
1679 if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
1680 return;
1685 struct givar_copy {
1686 VALUE obj;
1687 VALUE klass;
1688 st_table *iv_index_tbl;
1689 struct gen_ivtbl *ivtbl;
1692 static int
1693 gen_ivar_copy(ID id, VALUE val, st_data_t arg)
1695 struct givar_copy *c = (struct givar_copy *)arg;
1696 struct ivar_update ivup;
1698 ivup.iv_extended = 0;
1699 ivup.u.iv_index_tbl = c->iv_index_tbl;
1701 RB_VM_LOCK_ENTER();
1703 iv_index_tbl_extend(&ivup, id, c->klass);
1705 RB_VM_LOCK_LEAVE();
1707 if (ivup.index >= c->ivtbl->numiv) {
1708 uint32_t newsize = iv_index_tbl_newsize(&ivup);
1709 c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize);
1711 c->ivtbl->ivptr[ivup.index] = val;
1713 RB_OBJ_WRITTEN(c->obj, Qundef, val);
1715 return ST_CONTINUE;
1718 void
1719 rb_copy_generic_ivar(VALUE clone, VALUE obj)
1721 struct gen_ivtbl *ivtbl;
1723 rb_check_frozen(clone);
1725 if (!FL_TEST(obj, FL_EXIVAR)) {
1726 goto clear;
1728 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1729 struct givar_copy c;
1730 uint32_t i;
1732 if (gen_ivtbl_count(ivtbl) == 0)
1733 goto clear;
1735 if (gen_ivtbl_get(clone, 0, &c.ivtbl)) {
1736 for (i = 0; i < c.ivtbl->numiv; i++)
1737 c.ivtbl->ivptr[i] = Qundef;
1739 else {
1740 c.ivtbl = gen_ivtbl_resize(0, ivtbl->numiv);
1741 FL_SET(clone, FL_EXIVAR);
1744 VALUE klass = rb_obj_class(clone);
1745 c.iv_index_tbl = iv_index_tbl_make(clone, klass);
1746 c.obj = clone;
1747 c.klass = klass;
1748 gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c);
1750 * c.ivtbl may change in gen_ivar_copy due to realloc,
1751 * no need to free
1753 RB_VM_LOCK_ENTER();
1755 generic_ivtbl_no_ractor_check(clone);
1756 st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)c.ivtbl);
1758 RB_VM_LOCK_LEAVE();
1760 return;
1762 clear:
1763 if (FL_TEST(clone, FL_EXIVAR)) {
1764 rb_free_generic_ivar(clone);
1765 FL_UNSET(clone, FL_EXIVAR);
1769 void
1770 rb_replace_generic_ivar(VALUE clone, VALUE obj)
1772 RUBY_ASSERT(FL_TEST(obj, FL_EXIVAR));
1774 RB_VM_LOCK_ENTER();
1776 st_data_t ivtbl, obj_data = (st_data_t)obj;
1777 if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) {
1778 st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl);
1779 st_delete(generic_iv_tbl_, &obj_data, NULL);
1781 else {
1782 rb_bug("unreachable");
1785 RB_VM_LOCK_LEAVE();
1787 FL_SET(clone, FL_EXIVAR);
1790 void
1791 rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
1793 if (SPECIAL_CONST_P(obj)) return;
1794 switch (BUILTIN_TYPE(obj)) {
1795 case T_OBJECT:
1796 obj_ivar_each(obj, func, arg);
1797 break;
1798 case T_CLASS:
1799 case T_MODULE:
1800 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
1801 if (RCLASS_IV_TBL(obj)) {
1802 RB_VM_LOCK_ENTER();
1804 st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
1806 RB_VM_LOCK_LEAVE();
1808 break;
1809 default:
1810 if (FL_TEST(obj, FL_EXIVAR)) {
1811 gen_ivar_each(obj, func, arg);
1813 break;
1817 st_index_t
1818 rb_ivar_count(VALUE obj)
1820 st_table *tbl;
1822 if (SPECIAL_CONST_P(obj)) return 0;
1824 switch (BUILTIN_TYPE(obj)) {
1825 case T_OBJECT:
1826 if (ROBJECT_IV_INDEX_TBL(obj) != 0) {
1827 st_index_t i, count, num = ROBJECT_NUMIV(obj);
1828 const VALUE *const ivptr = ROBJECT_IVPTR(obj);
1829 for (i = count = 0; i < num; ++i) {
1830 if (ivptr[i] != Qundef) {
1831 count++;
1834 return count;
1836 break;
1837 case T_CLASS:
1838 case T_MODULE:
1839 if ((tbl = RCLASS_IV_TBL(obj)) != 0) {
1840 return tbl->num_entries;
1842 break;
1843 default:
1844 if (FL_TEST(obj, FL_EXIVAR)) {
1845 struct gen_ivtbl *ivtbl;
1847 if (gen_ivtbl_get(obj, 0, &ivtbl)) {
1848 return gen_ivtbl_count(ivtbl);
1851 break;
1853 return 0;
1856 static int
1857 ivar_i(st_data_t k, st_data_t v, st_data_t a)
1859 ID key = (ID)k;
1860 VALUE ary = (VALUE)a;
1862 if (rb_is_instance_id(key)) {
1863 rb_ary_push(ary, ID2SYM(key));
1865 return ST_CONTINUE;
1869 * call-seq:
1870 * obj.instance_variables -> array
1872 * Returns an array of instance variable names for the receiver. Note
1873 * that simply defining an accessor does not create the corresponding
1874 * instance variable.
1876 * class Fred
1877 * attr_accessor :a1
1878 * def initialize
1879 * @iv = 3
1880 * end
1881 * end
1882 * Fred.new.instance_variables #=> [:@iv]
1885 VALUE
1886 rb_obj_instance_variables(VALUE obj)
1888 VALUE ary;
1890 ary = rb_ary_new();
1891 rb_ivar_foreach(obj, ivar_i, ary);
1892 return ary;
1895 #define rb_is_constant_id rb_is_const_id
1896 #define rb_is_constant_name rb_is_const_name
1897 #define id_for_var(obj, name, part, type) \
1898 id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name")
1899 #define id_for_var_message(obj, name, type, message) \
1900 check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
1901 static ID
1902 check_id_type(VALUE obj, VALUE *pname,
1903 int (*valid_id_p)(ID), int (*valid_name_p)(VALUE),
1904 const char *message, size_t message_len)
1906 ID id = rb_check_id(pname);
1907 VALUE name = *pname;
1909 if (id ? !valid_id_p(id) : !valid_name_p(name)) {
1910 rb_name_err_raise_str(rb_fstring_new(message, message_len),
1911 obj, name);
1913 return id;
1917 * call-seq:
1918 * obj.remove_instance_variable(symbol) -> obj
1919 * obj.remove_instance_variable(string) -> obj
1921 * Removes the named instance variable from <i>obj</i>, returning that
1922 * variable's value.
1923 * String arguments are converted to symbols.
1925 * class Dummy
1926 * attr_reader :var
1927 * def initialize
1928 * @var = 99
1929 * end
1930 * def remove
1931 * remove_instance_variable(:@var)
1932 * end
1933 * end
1934 * d = Dummy.new
1935 * d.var #=> 99
1936 * d.remove #=> 99
1937 * d.var #=> nil
1940 VALUE
1941 rb_obj_remove_instance_variable(VALUE obj, VALUE name)
1943 VALUE val = Qnil;
1944 const ID id = id_for_var(obj, name, an, instance);
1945 st_data_t n, v;
1946 struct st_table *iv_index_tbl;
1947 uint32_t index;
1949 rb_check_frozen(obj);
1950 if (!id) {
1951 goto not_defined;
1954 switch (BUILTIN_TYPE(obj)) {
1955 case T_OBJECT:
1956 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1957 if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
1958 index < ROBJECT_NUMIV(obj) &&
1959 (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
1960 ROBJECT_IVPTR(obj)[index] = Qundef;
1961 return val;
1963 break;
1964 case T_CLASS:
1965 case T_MODULE:
1966 IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1967 n = id;
1968 if (RCLASS_IV_TBL(obj) && lock_st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
1969 return (VALUE)v;
1971 break;
1972 default:
1973 if (FL_TEST(obj, FL_EXIVAR)) {
1974 if (generic_ivar_remove(obj, id, &val)) {
1975 return val;
1978 break;
1981 not_defined:
1982 rb_name_err_raise("instance variable %1$s not defined",
1983 obj, name);
1984 UNREACHABLE_RETURN(Qnil);
1987 NORETURN(static void uninitialized_constant(VALUE, VALUE));
1988 static void
1989 uninitialized_constant(VALUE klass, VALUE name)
1991 if (klass && rb_class_real(klass) != rb_cObject)
1992 rb_name_err_raise("uninitialized constant %2$s::%1$s",
1993 klass, name);
1994 else
1995 rb_name_err_raise("uninitialized constant %1$s",
1996 klass, name);
1999 VALUE
2000 rb_const_missing(VALUE klass, VALUE name)
2002 VALUE value = rb_funcallv(klass, idConst_missing, 1, &name);
2003 rb_vm_inc_const_missing_count();
2004 return value;
2009 * call-seq:
2010 * mod.const_missing(sym) -> obj
2012 * Invoked when a reference is made to an undefined constant in
2013 * <i>mod</i>. It is passed a symbol for the undefined constant, and
2014 * returns a value to be used for that constant. The
2015 * following code is an example of the same:
2017 * def Foo.const_missing(name)
2018 * name # return the constant name as Symbol
2019 * end
2021 * Foo::UNDEFINED_CONST #=> :UNDEFINED_CONST: symbol returned
2023 * In the next example when a reference is made to an undefined constant,
2024 * it attempts to load a file whose name is the lowercase version of the
2025 * constant (thus class <code>Fred</code> is assumed to be in file
2026 * <code>fred.rb</code>). If found, it returns the loaded class. It
2027 * therefore implements an autoload feature similar to Kernel#autoload and
2028 * Module#autoload.
2030 * def Object.const_missing(name)
2031 * @looked_for ||= {}
2032 * str_name = name.to_s
2033 * raise "Class not found: #{name}" if @looked_for[str_name]
2034 * @looked_for[str_name] = 1
2035 * file = str_name.downcase
2036 * require file
2037 * klass = const_get(name)
2038 * return klass if klass
2039 * raise "Class not found: #{name}"
2040 * end
2044 VALUE
2045 rb_mod_const_missing(VALUE klass, VALUE name)
2047 VALUE ref = GET_EC()->private_const_reference;
2048 rb_vm_pop_cfunc_frame();
2049 if (ref) {
2050 rb_name_err_raise("private constant %2$s::%1$s referenced",
2051 ref, name);
2053 uninitialized_constant(klass, name);
2055 UNREACHABLE_RETURN(Qnil);
2058 static void
2059 autoload_mark(void *ptr)
2061 rb_mark_tbl_no_pin((st_table *)ptr);
2064 static void
2065 autoload_free(void *ptr)
2067 st_free_table((st_table *)ptr);
2070 static size_t
2071 autoload_memsize(const void *ptr)
2073 const st_table *tbl = ptr;
2074 return st_memsize(tbl);
2077 static void
2078 autoload_compact(void *ptr)
2080 rb_gc_update_tbl_refs((st_table *)ptr);
2083 static const rb_data_type_t autoload_data_type = {
2084 "autoload",
2085 {autoload_mark, autoload_free, autoload_memsize, autoload_compact,},
2086 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2089 #define check_autoload_table(av) \
2090 (struct st_table *)rb_check_typeddata((av), &autoload_data_type)
2092 static VALUE
2093 autoload_data(VALUE mod, ID id)
2095 struct st_table *tbl;
2096 st_data_t val;
2098 if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
2099 !(tbl = check_autoload_table((VALUE)val)) ||
2100 !st_lookup(tbl, (st_data_t)id, &val)) {
2101 return 0;
2103 return (VALUE)val;
2106 struct autoload_const {
2107 struct list_node cnode; /* <=> autoload_data_i.constants */
2108 VALUE mod;
2109 VALUE ad; /* autoload_data_i */
2110 VALUE value;
2111 VALUE file;
2112 ID id;
2113 rb_const_flag_t flag;
2114 int line;
2117 /* always on stack, no need to mark */
2118 struct autoload_state {
2119 struct autoload_const *ac;
2120 VALUE result;
2121 VALUE thread;
2122 struct list_head waitq;
2125 struct autoload_data_i {
2126 VALUE feature;
2127 struct autoload_state *state; /* points to on-stack struct */
2128 rb_serial_t fork_gen;
2129 struct list_head constants; /* <=> autoload_const.cnode */
2132 static void
2133 autoload_i_compact(void *ptr)
2135 struct autoload_data_i *p = ptr;
2136 p->feature = rb_gc_location(p->feature);
2139 static void
2140 autoload_i_mark(void *ptr)
2142 struct autoload_data_i *p = ptr;
2144 rb_gc_mark_movable(p->feature);
2146 /* allow GC to free us if no modules refer to this via autoload_const.ad */
2147 if (list_empty(&p->constants)) {
2148 rb_hash_delete(autoload_featuremap, p->feature);
2152 static void
2153 autoload_i_free(void *ptr)
2155 struct autoload_data_i *p = ptr;
2157 /* we may leak some memory at VM shutdown time, no big deal */
2158 if (list_empty(&p->constants)) {
2159 xfree(p);
2163 static size_t
2164 autoload_i_memsize(const void *ptr)
2166 return sizeof(struct autoload_data_i);
2169 static const rb_data_type_t autoload_data_i_type = {
2170 "autoload_i",
2171 {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact},
2172 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2175 static void
2176 autoload_c_compact(void *ptr)
2178 struct autoload_const *ac = ptr;
2180 ac->mod = rb_gc_location(ac->mod);
2181 ac->ad = rb_gc_location(ac->ad);
2182 ac->value = rb_gc_location(ac->value);
2183 ac->file = rb_gc_location(ac->file);
2186 static void
2187 autoload_c_mark(void *ptr)
2189 struct autoload_const *ac = ptr;
2191 rb_gc_mark_movable(ac->mod);
2192 rb_gc_mark_movable(ac->ad);
2193 rb_gc_mark_movable(ac->value);
2194 rb_gc_mark_movable(ac->file);
2197 static void
2198 autoload_c_free(void *ptr)
2200 struct autoload_const *ac = ptr;
2201 list_del(&ac->cnode);
2202 xfree(ac);
2205 static size_t
2206 autoload_c_memsize(const void *ptr)
2208 return sizeof(struct autoload_const);
2211 static const rb_data_type_t autoload_const_type = {
2212 "autoload_const",
2213 {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
2214 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2217 static struct autoload_data_i *
2218 get_autoload_data(VALUE acv, struct autoload_const **acp)
2220 struct autoload_const *ac = rb_check_typeddata(acv, &autoload_const_type);
2221 struct autoload_data_i *ele;
2223 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2224 /* do not reach across stack for ->state after forking: */
2225 if (ele && ele->state && ele->fork_gen != GET_VM()->fork_gen) {
2226 ele->state = 0;
2227 ele->fork_gen = 0;
2229 if (acp) *acp = ac;
2230 return ele;
2233 RUBY_FUNC_EXPORTED void
2234 rb_autoload(VALUE mod, ID id, const char *file)
2236 if (!file || !*file) {
2237 rb_raise(rb_eArgError, "empty file name");
2239 rb_autoload_str(mod, id, rb_fstring_cstr(file));
2242 void
2243 rb_autoload_str(VALUE mod, ID id, VALUE file)
2245 st_data_t av;
2246 VALUE ad;
2247 struct st_table *tbl;
2248 struct autoload_data_i *ele;
2249 rb_const_entry_t *ce;
2251 if (!rb_is_const_id(id)) {
2252 rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"",
2253 QUOTE_ID(id));
2256 Check_Type(file, T_STRING);
2257 if (!RSTRING_LEN(file)) {
2258 rb_raise(rb_eArgError, "empty file name");
2261 ce = rb_const_lookup(mod, id);
2262 if (ce && ce->value != Qundef) {
2263 return;
2266 rb_const_set(mod, id, Qundef);
2267 tbl = RCLASS_IV_TBL(mod);
2268 if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
2269 tbl = check_autoload_table((VALUE)av);
2271 else {
2272 if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
2273 av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
2274 st_add_direct(tbl, (st_data_t)autoload, av);
2275 RB_OBJ_WRITTEN(mod, Qnil, av);
2276 DATA_PTR(av) = tbl = st_init_numtable();
2279 file = rb_fstring(file);
2280 if (!autoload_featuremap) {
2281 autoload_featuremap = rb_ident_hash_new();
2282 rb_obj_hide(autoload_featuremap);
2283 rb_gc_register_mark_object(autoload_featuremap);
2285 ad = rb_hash_aref(autoload_featuremap, file);
2286 if (NIL_P(ad)) {
2287 ad = TypedData_Make_Struct(0, struct autoload_data_i,
2288 &autoload_data_i_type, ele);
2289 ele->feature = file;
2290 ele->state = 0;
2291 list_head_init(&ele->constants);
2292 rb_hash_aset(autoload_featuremap, file, ad);
2294 else {
2295 ele = rb_check_typeddata(ad, &autoload_data_i_type);
2298 VALUE acv;
2299 struct autoload_const *ac;
2300 acv = TypedData_Make_Struct(0, struct autoload_const,
2301 &autoload_const_type, ac);
2302 ac->mod = mod;
2303 ac->id = id;
2304 ac->value = Qundef;
2305 ac->flag = CONST_PUBLIC;
2306 ac->ad = ad;
2307 list_add_tail(&ele->constants, &ac->cnode);
2308 st_insert(tbl, (st_data_t)id, (st_data_t)acv);
2312 static void
2313 autoload_delete(VALUE mod, ID id)
2315 st_data_t val, load = 0, n = id;
2317 if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
2318 struct st_table *tbl = check_autoload_table((VALUE)val);
2319 struct autoload_data_i *ele;
2320 struct autoload_const *ac;
2322 st_delete(tbl, &n, &load);
2323 /* Qfalse can indicate already deleted */
2324 if (load != Qfalse) {
2325 ele = get_autoload_data((VALUE)load, &ac);
2326 VM_ASSERT(ele);
2327 if (ele) {
2328 VM_ASSERT(!list_empty(&ele->constants));
2332 * we must delete here to avoid "already initialized" warnings
2333 * with parallel autoload. Using list_del_init here so list_del
2334 * works in autoload_c_free
2336 list_del_init(&ac->cnode);
2338 if (tbl->num_entries == 0) {
2339 n = autoload;
2340 st_delete(RCLASS_IV_TBL(mod), &n, &val);
2346 static VALUE
2347 check_autoload_required(VALUE mod, ID id, const char **loadingpath)
2349 VALUE file;
2350 VALUE load = autoload_data(mod, id);
2351 struct autoload_data_i *ele;
2352 const char *loading;
2354 if (!load || !(ele = get_autoload_data(load, 0))) {
2355 return 0;
2357 file = ele->feature;
2358 Check_Type(file, T_STRING);
2359 if (!RSTRING_LEN(file) || !*RSTRING_PTR(file)) {
2360 rb_raise(rb_eArgError, "empty file name");
2364 * if somebody else is autoloading, we MUST wait for them, since
2365 * rb_provide_feature can provide a feature before autoload_const_set
2366 * completes. We must wait until autoload_const_set finishes in
2367 * the other thread.
2369 if (ele->state && ele->state->thread != rb_thread_current()) {
2370 return load;
2373 loading = RSTRING_PTR(file);
2374 if (!rb_feature_provided(loading, &loading)) {
2375 return load;
2377 if (loadingpath && loading) {
2378 *loadingpath = loading;
2379 return load;
2381 return 0;
2384 static struct autoload_const *autoloading_const_entry(VALUE mod, ID id);
2386 MJIT_FUNC_EXPORTED int
2387 rb_autoloading_value(VALUE mod, ID id, VALUE* value, rb_const_flag_t *flag)
2389 struct autoload_const *ac = autoloading_const_entry(mod, id);
2390 if (!ac) return FALSE;
2392 if (value) {
2393 *value = ac->value;
2395 if (flag) {
2396 *flag = ac->flag;
2398 return TRUE;
2401 struct autoload_const *
2402 autoloading_const_entry(VALUE mod, ID id)
2404 VALUE load = autoload_data(mod, id);
2405 struct autoload_data_i *ele;
2406 struct autoload_const *ac;
2408 if (!load || !(ele = get_autoload_data(load, &ac))) {
2409 return 0;
2412 if (ele->state && ele->state->thread == rb_thread_current()) {
2413 if (ac->value != Qundef) {
2414 return ac;
2417 return 0;
2420 static int
2421 autoload_defined_p(VALUE mod, ID id)
2423 rb_const_entry_t *ce = rb_const_lookup(mod, id);
2425 if (!ce || ce->value != Qundef) {
2426 return 0;
2428 return !rb_autoloading_value(mod, id, NULL, NULL);
2431 static void const_tbl_update(struct autoload_const *);
2433 static VALUE
2434 autoload_const_set(struct autoload_const *ac)
2436 VALUE klass = ac->mod;
2437 ID id = ac->id;
2438 check_before_mod_set(klass, id, ac->value, "constant");
2440 RB_VM_LOCK_ENTER();
2442 const_tbl_update(ac);
2444 RB_VM_LOCK_LEAVE();
2446 return 0; /* ignored */
2449 static VALUE
2450 autoload_require(VALUE arg)
2452 struct autoload_state *state = (struct autoload_state *)arg;
2453 struct autoload_const *ac = state->ac;
2454 struct autoload_data_i *ele;
2456 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2457 /* this may release GVL and switch threads: */
2458 state->result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1,
2459 ele->feature);
2461 return state->result;
2464 static VALUE
2465 autoload_reset(VALUE arg)
2467 struct autoload_state *state = (struct autoload_state *)arg;
2468 int need_wakeups = 0;
2469 struct autoload_const *ac = state->ac;
2470 struct autoload_data_i *ele;
2472 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2473 if (ele->state == state) {
2474 need_wakeups = 1;
2475 ele->state = 0;
2476 ele->fork_gen = 0;
2479 /* At the last, move a value defined in autoload to constant table */
2480 if (RTEST(state->result)) {
2481 struct autoload_const *next;
2483 list_for_each_safe(&ele->constants, ac, next, cnode) {
2484 if (ac->value != Qundef) {
2485 autoload_const_set(ac);
2490 /* wakeup any waiters we had */
2491 if (need_wakeups) {
2492 struct autoload_state *cur = 0, *nxt;
2494 list_for_each_safe(&state->waitq, cur, nxt, waitq.n) {
2495 VALUE th = cur->thread;
2497 cur->thread = Qfalse;
2498 list_del_init(&cur->waitq.n); /* idempotent */
2501 * cur is stored on the stack of cur->waiting_th,
2502 * do not touch cur after waking up waiting_th
2504 rb_thread_wakeup_alive(th);
2508 return 0; /* ignored */
2511 static VALUE
2512 autoload_sleep(VALUE arg)
2514 struct autoload_state *state = (struct autoload_state *)arg;
2517 * autoload_reset in other thread will resume us and remove us
2518 * from the waitq list
2520 do {
2521 rb_thread_sleep_deadly();
2522 } while (state->thread != Qfalse);
2524 return Qfalse;
2527 static VALUE
2528 autoload_sleep_done(VALUE arg)
2530 struct autoload_state *state = (struct autoload_state *)arg;
2532 if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) {
2533 list_del(&state->waitq.n); /* idempotent after list_del_init */
2536 return Qfalse;
2539 VALUE
2540 rb_autoload_load(VALUE mod, ID id)
2542 VALUE load, result;
2543 const char *loading = 0, *src;
2544 struct autoload_data_i *ele;
2545 struct autoload_const *ac;
2546 struct autoload_state state;
2547 int flag = -1;
2548 rb_const_entry_t *ce;
2550 if (!autoload_defined_p(mod, id)) return Qfalse;
2551 load = check_autoload_required(mod, id, &loading);
2552 if (!load) return Qfalse;
2553 src = rb_sourcefile();
2554 if (src && loading && strcmp(src, loading) == 0) return Qfalse;
2556 if (UNLIKELY(!rb_ractor_main_p())) {
2557 rb_raise(rb_eRactorUnsafeError, "require by autoload on non-main Ractor is not supported (%s)", rb_id2name(id));
2560 if ((ce = rb_const_lookup(mod, id))) {
2561 flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2564 /* set ele->state for a marker of autoloading thread */
2565 if (!(ele = get_autoload_data(load, &ac))) {
2566 return Qfalse;
2568 state.ac = ac;
2569 state.thread = rb_thread_current();
2570 if (!ele->state) {
2571 ele->state = &state;
2572 ele->fork_gen = GET_VM()->fork_gen;
2575 * autoload_reset will wake up any threads added to this
2576 * if and only if the GVL is released during autoload_require
2578 list_head_init(&state.waitq);
2580 else if (state.thread == ele->state->thread) {
2581 return Qfalse;
2583 else {
2584 list_add_tail(&ele->state->waitq, &state.waitq.n);
2586 rb_ensure(autoload_sleep, (VALUE)&state,
2587 autoload_sleep_done, (VALUE)&state);
2590 /* autoload_data_i can be deleted by another thread while require */
2591 state.result = Qfalse;
2592 result = rb_ensure(autoload_require, (VALUE)&state,
2593 autoload_reset, (VALUE)&state);
2595 if (!(ce = rb_const_lookup(mod, id)) || ce->value == Qundef) {
2596 rb_const_remove(mod, id);
2598 else if (flag > 0) {
2599 ce->flag |= flag;
2601 RB_GC_GUARD(load);
2602 return result;
2605 VALUE
2606 rb_autoload_p(VALUE mod, ID id)
2608 return rb_autoload_at_p(mod, id, TRUE);
2611 VALUE
2612 rb_autoload_at_p(VALUE mod, ID id, int recur)
2614 VALUE load;
2615 struct autoload_data_i *ele;
2617 while (!autoload_defined_p(mod, id)) {
2618 if (!recur) return Qnil;
2619 mod = RCLASS_SUPER(mod);
2620 if (!mod) return Qnil;
2622 load = check_autoload_required(mod, id, 0);
2623 if (!load) return Qnil;
2624 return (ele = get_autoload_data(load, 0)) ? ele->feature : Qnil;
2627 MJIT_FUNC_EXPORTED void
2628 rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
2630 if (RB_CONST_DEPRECATED_P(ce) &&
2631 rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
2632 if (klass == rb_cObject) {
2633 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
2635 else {
2636 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
2637 rb_class_name(klass), QUOTE_ID(id));
2642 static VALUE
2643 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2645 VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
2646 if (c != Qundef) {
2647 if (UNLIKELY(!rb_ractor_main_p())) {
2648 if (!rb_ractor_shareable_p(c)) {
2649 rb_raise(rb_eRactorIsolationError, "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main Ractor.", rb_class_path(klass), rb_id2name(id));
2652 return c;
2654 return rb_const_missing(klass, ID2SYM(id));
2657 static VALUE
2658 rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2660 VALUE value, current;
2661 bool first_iteration = true;
2663 for (current = klass;
2664 RTEST(current);
2665 current = RCLASS_SUPER(current), first_iteration = false) {
2666 VALUE tmp;
2667 VALUE am = 0;
2668 rb_const_entry_t *ce;
2670 if (!first_iteration && RCLASS_ORIGIN(current) != current) {
2671 // This item in the super chain has an origin iclass
2672 // that comes later in the chain. Skip this item so
2673 // prepended modules take precedence.
2674 continue;
2677 // Do lookup in original class or module in case we are at an origin
2678 // iclass in the chain.
2679 tmp = current;
2680 if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass;
2682 // Do the lookup. Loop in case of autoload.
2683 while ((ce = rb_const_lookup(tmp, id))) {
2684 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2685 GET_EC()->private_const_reference = tmp;
2686 return Qundef;
2688 rb_const_warn_if_deprecated(ce, tmp, id);
2689 value = ce->value;
2690 if (value == Qundef) {
2691 struct autoload_const *ac;
2692 if (am == tmp) break;
2693 am = tmp;
2694 ac = autoloading_const_entry(tmp, id);
2695 if (ac) return ac->value;
2696 rb_autoload_load(tmp, id);
2697 continue;
2699 if (exclude && tmp == rb_cObject) {
2700 goto not_found;
2702 return value;
2704 if (!recurse) break;
2707 not_found:
2708 GET_EC()->private_const_reference = 0;
2709 return Qundef;
2712 static VALUE
2713 rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
2715 VALUE value;
2717 if (klass == rb_cObject) exclude = FALSE;
2718 value = rb_const_search_from(klass, id, exclude, recurse, visibility);
2719 if (value != Qundef) return value;
2720 if (exclude) return value;
2721 if (BUILTIN_TYPE(klass) != T_MODULE) return value;
2722 /* search global const too, if klass is a module */
2723 return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
2726 VALUE
2727 rb_const_get_from(VALUE klass, ID id)
2729 return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
2732 VALUE
2733 rb_const_get(VALUE klass, ID id)
2735 return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
2738 VALUE
2739 rb_const_get_at(VALUE klass, ID id)
2741 return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
2744 MJIT_FUNC_EXPORTED VALUE
2745 rb_public_const_get_from(VALUE klass, ID id)
2747 return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
2750 MJIT_FUNC_EXPORTED VALUE
2751 rb_public_const_get_at(VALUE klass, ID id)
2753 return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
2756 NORETURN(static void undefined_constant(VALUE mod, VALUE name));
2757 static void
2758 undefined_constant(VALUE mod, VALUE name)
2760 rb_name_err_raise("constant %2$s::%1$s not defined",
2761 mod, name);
2764 static VALUE
2765 rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2767 while (RTEST(klass)) {
2768 rb_const_entry_t *ce;
2770 while ((ce = rb_const_lookup(klass, id))) {
2771 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2772 return Qnil;
2774 if (exclude && klass == rb_cObject) {
2775 goto not_found;
2777 if (NIL_P(ce->file)) return rb_ary_new();
2778 return rb_assoc_new(ce->file, INT2NUM(ce->line));
2780 if (!recurse) break;
2781 klass = RCLASS_SUPER(klass);
2784 not_found:
2785 return Qnil;
2788 static VALUE
2789 rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility)
2791 VALUE loc;
2793 if (klass == rb_cObject) exclude = FALSE;
2794 loc = rb_const_location_from(klass, id, exclude, recurse, visibility);
2795 if (!NIL_P(loc)) return loc;
2796 if (exclude) return loc;
2797 if (BUILTIN_TYPE(klass) != T_MODULE) return loc;
2798 /* search global const too, if klass is a module */
2799 return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility);
2802 VALUE
2803 rb_const_source_location(VALUE klass, ID id)
2805 return rb_const_location(klass, id, FALSE, TRUE, FALSE);
2808 MJIT_FUNC_EXPORTED VALUE
2809 rb_const_source_location_at(VALUE klass, ID id)
2811 return rb_const_location(klass, id, TRUE, FALSE, FALSE);
2815 * call-seq:
2816 * remove_const(sym) -> obj
2818 * Removes the definition of the given constant, returning that
2819 * constant's previous value. If that constant referred to
2820 * a module, this will not change that module's name and can lead
2821 * to confusion.
2824 VALUE
2825 rb_mod_remove_const(VALUE mod, VALUE name)
2827 const ID id = id_for_var(mod, name, a, constant);
2829 if (!id) {
2830 undefined_constant(mod, name);
2832 return rb_const_remove(mod, id);
2835 VALUE
2836 rb_const_remove(VALUE mod, ID id)
2838 VALUE val;
2839 rb_const_entry_t *ce;
2841 rb_check_frozen(mod);
2842 ce = rb_const_lookup(mod, id);
2843 if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2844 if (rb_const_defined_at(mod, id)) {
2845 rb_name_err_raise("cannot remove %2$s::%1$s",
2846 mod, ID2SYM(id));
2848 undefined_constant(mod, ID2SYM(id));
2851 rb_clear_constant_cache();
2853 val = ce->value;
2854 if (val == Qundef) {
2855 autoload_delete(mod, id);
2856 val = Qnil;
2858 xfree(ce);
2859 return val;
2862 static int
2863 cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
2865 if (existing) return ST_STOP;
2866 *v = a;
2867 return ST_CONTINUE;
2870 static enum rb_id_table_iterator_result
2871 sv_i(ID key, VALUE v, void *a)
2873 rb_const_entry_t *ce = (rb_const_entry_t *)v;
2874 st_table *tbl = a;
2876 if (rb_is_const_id(key)) {
2877 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2879 return ID_TABLE_CONTINUE;
2882 static enum rb_id_table_iterator_result
2883 rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
2885 if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
2886 rb_ary_push((VALUE)ary, ID2SYM(const_name));
2888 return ID_TABLE_CONTINUE;
2891 static VALUE
2892 rb_local_constants(VALUE mod)
2894 struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
2895 VALUE ary;
2897 if (!tbl) return rb_ary_new2(0);
2899 RB_VM_LOCK_ENTER();
2901 ary = rb_ary_new2(rb_id_table_size(tbl));
2902 rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
2904 RB_VM_LOCK_LEAVE();
2906 return ary;
2909 void*
2910 rb_mod_const_at(VALUE mod, void *data)
2912 st_table *tbl = data;
2913 if (!tbl) {
2914 tbl = st_init_numtable();
2916 if (RCLASS_CONST_TBL(mod)) {
2917 RB_VM_LOCK_ENTER();
2919 rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
2921 RB_VM_LOCK_LEAVE();
2923 return tbl;
2926 void*
2927 rb_mod_const_of(VALUE mod, void *data)
2929 VALUE tmp = mod;
2930 for (;;) {
2931 data = rb_mod_const_at(tmp, data);
2932 tmp = RCLASS_SUPER(tmp);
2933 if (!tmp) break;
2934 if (tmp == rb_cObject && mod != rb_cObject) break;
2936 return data;
2939 static int
2940 list_i(st_data_t key, st_data_t value, VALUE ary)
2942 ID sym = (ID)key;
2943 rb_const_entry_t *ce = (rb_const_entry_t *)value;
2944 if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
2945 return ST_CONTINUE;
2948 VALUE
2949 rb_const_list(void *data)
2951 st_table *tbl = data;
2952 VALUE ary;
2954 if (!tbl) return rb_ary_new2(0);
2955 ary = rb_ary_new2(tbl->num_entries);
2956 st_foreach_safe(tbl, list_i, ary);
2957 st_free_table(tbl);
2959 return ary;
2963 * call-seq:
2964 * mod.constants(inherit=true) -> array
2966 * Returns an array of the names of the constants accessible in
2967 * <i>mod</i>. This includes the names of constants in any included
2968 * modules (example at start of section), unless the <i>inherit</i>
2969 * parameter is set to <code>false</code>.
2971 * The implementation makes no guarantees about the order in which the
2972 * constants are yielded.
2974 * IO.constants.include?(:SYNC) #=> true
2975 * IO.constants(false).include?(:SYNC) #=> false
2977 * Also see Module#const_defined?.
2980 VALUE
2981 rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
2983 bool inherit = true;
2985 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
2987 if (inherit) {
2988 return rb_const_list(rb_mod_const_of(mod, 0));
2990 else {
2991 return rb_local_constants(mod);
2995 static int
2996 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2998 VALUE tmp;
2999 int mod_retry = 0;
3000 rb_const_entry_t *ce;
3002 tmp = klass;
3003 retry:
3004 while (tmp) {
3005 if ((ce = rb_const_lookup(tmp, id))) {
3006 if (visibility && RB_CONST_PRIVATE_P(ce)) {
3007 return (int)Qfalse;
3009 if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
3010 !rb_autoloading_value(tmp, id, NULL, NULL))
3011 return (int)Qfalse;
3013 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3014 return (int)Qfalse;
3017 return (int)Qtrue;
3019 if (!recurse) break;
3020 tmp = RCLASS_SUPER(tmp);
3022 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
3023 mod_retry = 1;
3024 tmp = rb_cObject;
3025 goto retry;
3027 return (int)Qfalse;
3031 rb_const_defined_from(VALUE klass, ID id)
3033 return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
3037 rb_const_defined(VALUE klass, ID id)
3039 return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
3043 rb_const_defined_at(VALUE klass, ID id)
3045 return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
3048 MJIT_FUNC_EXPORTED int
3049 rb_public_const_defined_from(VALUE klass, ID id)
3051 return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
3054 static void
3055 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
3057 rb_check_frozen(klass);
3060 static void set_namespace_path(VALUE named_namespace, VALUE name);
3062 static enum rb_id_table_iterator_result
3063 set_namespace_path_i(ID id, VALUE v, void *payload)
3065 rb_const_entry_t *ce = (rb_const_entry_t *)v;
3066 VALUE value = ce->value;
3067 int has_permanent_classpath;
3068 VALUE parental_path = *((VALUE *) payload);
3069 if (!rb_is_const_id(id) || !rb_namespace_p(value)) {
3070 return ID_TABLE_CONTINUE;
3072 classname(value, &has_permanent_classpath);
3073 if (has_permanent_classpath) {
3074 return ID_TABLE_CONTINUE;
3076 set_namespace_path(value, build_const_path(parental_path, id));
3077 if (RCLASS_IV_TBL(value)) {
3078 st_data_t tmp = tmp_classpath;
3079 st_delete(RCLASS_IV_TBL(value), &tmp, 0);
3082 return ID_TABLE_CONTINUE;
3086 * Assign permanent classpaths to all namespaces that are directly or indirectly
3087 * nested under +named_namespace+. +named_namespace+ must have a permanent
3088 * classpath.
3090 static void
3091 set_namespace_path(VALUE named_namespace, VALUE namespace_path)
3093 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3095 RB_VM_LOCK_ENTER();
3097 rb_class_ivar_set(named_namespace, classpath, namespace_path);
3098 if (const_table) {
3099 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3102 RB_VM_LOCK_LEAVE();
3105 static void
3106 const_added(VALUE klass, ID const_name)
3108 if (GET_VM()->running) {
3109 VALUE name = ID2SYM(const_name);
3110 rb_funcallv(klass, idConst_added, 1, &name);
3114 void
3115 rb_const_set(VALUE klass, ID id, VALUE val)
3117 rb_const_entry_t *ce;
3119 if (NIL_P(klass)) {
3120 rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
3121 QUOTE_ID(id));
3124 if (!rb_ractor_main_p() && !rb_ractor_shareable_p(val)) {
3125 rb_raise(rb_eRactorIsolationError, "can not set constants with non-shareable objects by non-main Ractors");
3128 check_before_mod_set(klass, id, val, "constant");
3130 RB_VM_LOCK_ENTER();
3132 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3133 if (!tbl) {
3134 RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
3135 rb_clear_constant_cache();
3136 ce = ZALLOC(rb_const_entry_t);
3137 rb_id_table_insert(tbl, id, (VALUE)ce);
3138 setup_const_entry(ce, klass, val, CONST_PUBLIC);
3140 else {
3141 struct autoload_const ac = {
3142 .mod = klass, .id = id,
3143 .value = val, .flag = CONST_PUBLIC,
3144 /* fill the rest with 0 */
3146 const_tbl_update(&ac);
3149 RB_VM_LOCK_LEAVE();
3152 * Resolve and cache class name immediately to resolve ambiguity
3153 * and avoid order-dependency on const_tbl
3155 if (rb_cObject && rb_namespace_p(val)) {
3156 int val_path_permanent;
3157 VALUE val_path = classname(val, &val_path_permanent);
3158 if (NIL_P(val_path) || !val_path_permanent) {
3159 if (klass == rb_cObject) {
3160 set_namespace_path(val, rb_id2str(id));
3162 else {
3163 int parental_path_permanent;
3164 VALUE parental_path = classname(klass, &parental_path_permanent);
3165 if (NIL_P(parental_path)) {
3166 int throwaway;
3167 parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
3169 if (parental_path_permanent && !val_path_permanent) {
3170 set_namespace_path(val, build_const_path(parental_path, id));
3172 else if (!parental_path_permanent && NIL_P(val_path)) {
3173 ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
3178 const_added(klass, id);
3181 static struct autoload_data_i *
3182 current_autoload_data(VALUE mod, ID id, struct autoload_const **acp)
3184 struct autoload_data_i *ele;
3185 VALUE load = autoload_data(mod, id);
3186 if (!load) return 0;
3187 ele = get_autoload_data(load, acp);
3188 if (!ele) return 0;
3189 /* for autoloading thread, keep the defined value to autoloading storage */
3190 if (ele->state && (ele->state->thread == rb_thread_current())) {
3191 return ele;
3193 return 0;
3196 static void
3197 const_tbl_update(struct autoload_const *ac)
3199 VALUE value;
3200 VALUE klass = ac->mod;
3201 VALUE val = ac->value;
3202 ID id = ac->id;
3203 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3204 rb_const_flag_t visibility = ac->flag;
3205 rb_const_entry_t *ce;
3207 if (rb_id_table_lookup(tbl, id, &value)) {
3208 ce = (rb_const_entry_t *)value;
3209 if (ce->value == Qundef) {
3210 struct autoload_data_i *ele = current_autoload_data(klass, id, &ac);
3212 if (ele) {
3213 rb_clear_constant_cache();
3215 ac->value = val; /* autoload_i is non-WB-protected */
3216 ac->file = rb_source_location(&ac->line);
3218 else {
3219 /* otherwise autoloaded constant, allow to override */
3220 autoload_delete(klass, id);
3221 ce->flag = visibility;
3222 RB_OBJ_WRITE(klass, &ce->value, val);
3223 RB_OBJ_WRITE(klass, &ce->file, ac->file);
3224 ce->line = ac->line;
3226 return;
3228 else {
3229 VALUE name = QUOTE_ID(id);
3230 visibility = ce->flag;
3231 if (klass == rb_cObject)
3232 rb_warn("already initialized constant %"PRIsVALUE"", name);
3233 else
3234 rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
3235 rb_class_name(klass), name);
3236 if (!NIL_P(ce->file) && ce->line) {
3237 rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
3238 "previous definition of %"PRIsVALUE" was here", name);
3241 rb_clear_constant_cache();
3242 setup_const_entry(ce, klass, val, visibility);
3244 else {
3245 rb_clear_constant_cache();
3247 ce = ZALLOC(rb_const_entry_t);
3248 rb_id_table_insert(tbl, id, (VALUE)ce);
3249 setup_const_entry(ce, klass, val, visibility);
3253 static void
3254 setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
3255 rb_const_flag_t visibility)
3257 ce->flag = visibility;
3258 RB_OBJ_WRITE(klass, &ce->value, val);
3259 RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
3262 void
3263 rb_define_const(VALUE klass, const char *name, VALUE val)
3265 ID id = rb_intern(name);
3267 if (!rb_is_const_id(id)) {
3268 rb_warn("rb_define_const: invalid name `%s' for constant", name);
3270 rb_gc_register_mark_object(val);
3271 rb_const_set(klass, id, val);
3274 void
3275 rb_define_global_const(const char *name, VALUE val)
3277 rb_define_const(rb_cObject, name, val);
3280 static void
3281 set_const_visibility(VALUE mod, int argc, const VALUE *argv,
3282 rb_const_flag_t flag, rb_const_flag_t mask)
3284 int i;
3285 rb_const_entry_t *ce;
3286 ID id;
3288 rb_class_modify_check(mod);
3289 if (argc == 0) {
3290 rb_warning("%"PRIsVALUE" with no argument is just ignored",
3291 QUOTE_ID(rb_frame_callee()));
3292 return;
3295 for (i = 0; i < argc; i++) {
3296 struct autoload_const *ac;
3297 VALUE val = argv[i];
3298 id = rb_check_id(&val);
3299 if (!id) {
3300 if (i > 0) {
3301 rb_clear_constant_cache();
3304 undefined_constant(mod, val);
3306 if ((ce = rb_const_lookup(mod, id))) {
3307 ce->flag &= ~mask;
3308 ce->flag |= flag;
3309 if (ce->value == Qundef) {
3310 struct autoload_data_i *ele;
3312 ele = current_autoload_data(mod, id, &ac);
3313 if (ele) {
3314 ac->flag &= ~mask;
3315 ac->flag |= flag;
3319 else {
3320 if (i > 0) {
3321 rb_clear_constant_cache();
3323 undefined_constant(mod, ID2SYM(id));
3326 rb_clear_constant_cache();
3329 void
3330 rb_deprecate_constant(VALUE mod, const char *name)
3332 rb_const_entry_t *ce;
3333 ID id;
3334 long len = strlen(name);
3336 rb_class_modify_check(mod);
3337 if (!(id = rb_check_id_cstr(name, len, NULL))) {
3338 undefined_constant(mod, rb_fstring_new(name, len));
3340 if (!(ce = rb_const_lookup(mod, id))) {
3341 undefined_constant(mod, ID2SYM(id));
3343 ce->flag |= CONST_DEPRECATED;
3347 * call-seq:
3348 * mod.private_constant(symbol, ...) => mod
3350 * Makes a list of existing constants private.
3353 VALUE
3354 rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
3356 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
3357 return obj;
3361 * call-seq:
3362 * mod.public_constant(symbol, ...) => mod
3364 * Makes a list of existing constants public.
3367 VALUE
3368 rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
3370 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
3371 return obj;
3375 * call-seq:
3376 * mod.deprecate_constant(symbol, ...) => mod
3378 * Makes a list of existing constants deprecated. Attempt
3379 * to refer to them will produce a warning.
3381 * module HTTP
3382 * NotFound = Exception.new
3383 * NOT_FOUND = NotFound # previous version of the library used this name
3385 * deprecate_constant :NOT_FOUND
3386 * end
3388 * HTTP::NOT_FOUND
3389 * # warning: constant HTTP::NOT_FOUND is deprecated
3393 VALUE
3394 rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
3396 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3397 return obj;
3400 static VALUE
3401 original_module(VALUE c)
3403 if (RB_TYPE_P(c, T_ICLASS))
3404 return RBASIC(c)->klass;
3405 return c;
3408 static int
3409 cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3411 if (!RCLASS_IV_TBL(klass)) return 0;
3412 return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v);
3415 static VALUE
3416 cvar_front_klass(VALUE klass)
3418 if (FL_TEST(klass, FL_SINGLETON)) {
3419 VALUE obj = rb_ivar_get(klass, id__attached__);
3420 if (rb_namespace_p(obj)) {
3421 return obj;
3424 return RCLASS_SUPER(klass);
3427 static void
3428 cvar_overtaken(VALUE front, VALUE target, ID id)
3430 if (front && target != front) {
3431 st_data_t did = (st_data_t)id;
3433 if (original_module(front) != original_module(target)) {
3434 rb_raise(rb_eRuntimeError,
3435 "class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3436 ID2SYM(id), rb_class_name(original_module(front)),
3437 rb_class_name(original_module(target)));
3439 if (BUILTIN_TYPE(front) == T_CLASS) {
3440 st_delete(RCLASS_IV_TBL(front), &did, 0);
3445 static VALUE
3446 find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id)
3448 VALUE v = Qundef;
3449 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR();
3450 if (cvar_lookup_at(klass, id, (&v))) {
3451 if (!*front) {
3452 *front = klass;
3454 *target = klass;
3457 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) {
3458 if (cvar_lookup_at(klass, id, (&v))) {
3459 if (!*front) {
3460 *front = klass;
3462 *target = klass;
3466 return v;
3469 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3470 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3471 if (cvar_lookup_at(klass, id, (v))) { \
3472 r; \
3476 #define CVAR_LOOKUP(v,r) do {\
3477 CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
3478 if (cvar_lookup_at(klass, id, (v))) {r;}\
3479 CVAR_FOREACH_ANCESTORS(klass, v, r);\
3480 } while(0)
3482 static void
3483 check_for_cvar_table(VALUE subclass, VALUE key)
3485 st_table *tbl = RCLASS_IV_TBL(subclass);
3487 if (tbl && st_lookup(tbl, key, NULL)) {
3488 RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
3489 ruby_vm_global_cvar_state++;
3490 return;
3493 rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
3496 void
3497 rb_cvar_set(VALUE klass, ID id, VALUE val)
3499 VALUE tmp, front = 0, target = 0;
3501 tmp = klass;
3502 CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3503 if (target) {
3504 cvar_overtaken(front, target, id);
3506 else {
3507 target = tmp;
3510 if (RB_TYPE_P(target, T_ICLASS)) {
3511 target = RBASIC(target)->klass;
3513 check_before_mod_set(target, id, val, "class variable");
3515 int result = rb_class_ivar_set(target, id, val);
3517 struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
3519 if (!rb_cvc_tbl) {
3520 rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
3523 struct rb_cvar_class_tbl_entry *ent;
3524 VALUE ent_data;
3526 if (!rb_id_table_lookup(rb_cvc_tbl, id, &ent_data)) {
3527 ent = ALLOC(struct rb_cvar_class_tbl_entry);
3528 ent->class_value = target;
3529 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3530 rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent);
3531 RB_DEBUG_COUNTER_INC(cvar_inline_miss);
3533 else {
3534 ent = (void *)ent_data;
3535 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3538 // Break the cvar cache if this is a new class variable
3539 // and target is a module or a subclass with the same
3540 // cvar in this lookup.
3541 if (result == 0) {
3542 if (RB_TYPE_P(target, T_CLASS)) {
3543 if (RCLASS_SUBCLASSES(target)) {
3544 rb_class_foreach_subclass(target, check_for_cvar_table, id);
3550 VALUE
3551 rb_cvar_find(VALUE klass, ID id, VALUE *front)
3553 VALUE target = 0;
3554 VALUE value;
3556 value = find_cvar(klass, front, &target, id);
3557 if (!target) {
3558 rb_name_err_raise("uninitialized class variable %1$s in %2$s",
3559 klass, ID2SYM(id));
3561 cvar_overtaken(*front, target, id);
3562 return (VALUE)value;
3565 VALUE
3566 rb_cvar_get(VALUE klass, ID id)
3568 VALUE front = 0;
3569 return rb_cvar_find(klass, id, &front);
3572 VALUE
3573 rb_cvar_defined(VALUE klass, ID id)
3575 if (!klass) return Qfalse;
3576 CVAR_LOOKUP(0,return Qtrue);
3577 return Qfalse;
3580 static ID
3581 cv_intern(VALUE klass, const char *name)
3583 ID id = rb_intern(name);
3584 if (!rb_is_class_id(id)) {
3585 rb_name_err_raise("wrong class variable name %1$s",
3586 klass, rb_str_new_cstr(name));
3588 return id;
3591 void
3592 rb_cv_set(VALUE klass, const char *name, VALUE val)
3594 ID id = cv_intern(klass, name);
3595 rb_cvar_set(klass, id, val);
3598 VALUE
3599 rb_cv_get(VALUE klass, const char *name)
3601 ID id = cv_intern(klass, name);
3602 return rb_cvar_get(klass, id);
3605 void
3606 rb_define_class_variable(VALUE klass, const char *name, VALUE val)
3608 rb_cv_set(klass, name, val);
3611 static int
3612 cv_i(st_data_t k, st_data_t v, st_data_t a)
3614 ID key = (ID)k;
3615 st_table *tbl = (st_table *)a;
3617 if (rb_is_class_id(key)) {
3618 st_update(tbl, (st_data_t)key, cv_i_update, 0);
3620 return ST_CONTINUE;
3623 static void*
3624 mod_cvar_at(VALUE mod, void *data)
3626 st_table *tbl = data;
3627 if (!tbl) {
3628 tbl = st_init_numtable();
3630 if (RCLASS_IV_TBL(mod)) {
3631 st_foreach_safe(RCLASS_IV_TBL(mod), cv_i, (st_data_t)tbl);
3633 return tbl;
3636 static void*
3637 mod_cvar_of(VALUE mod, void *data)
3639 VALUE tmp = mod;
3640 if (FL_TEST(mod, FL_SINGLETON)) {
3641 if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) {
3642 data = mod_cvar_at(tmp, data);
3643 tmp = cvar_front_klass(tmp);
3646 for (;;) {
3647 data = mod_cvar_at(tmp, data);
3648 tmp = RCLASS_SUPER(tmp);
3649 if (!tmp) break;
3651 return data;
3654 static int
3655 cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3657 ID sym = (ID)key;
3658 rb_ary_push(ary, ID2SYM(sym));
3659 return ST_CONTINUE;
3662 static VALUE
3663 cvar_list(void *data)
3665 st_table *tbl = data;
3666 VALUE ary;
3668 if (!tbl) return rb_ary_new2(0);
3669 ary = rb_ary_new2(tbl->num_entries);
3670 st_foreach_safe(tbl, cv_list_i, ary);
3671 st_free_table(tbl);
3673 return ary;
3677 * call-seq:
3678 * mod.class_variables(inherit=true) -> array
3680 * Returns an array of the names of class variables in <i>mod</i>.
3681 * This includes the names of class variables in any included
3682 * modules, unless the <i>inherit</i> parameter is set to
3683 * <code>false</code>.
3685 * class One
3686 * @@var1 = 1
3687 * end
3688 * class Two < One
3689 * @@var2 = 2
3690 * end
3691 * One.class_variables #=> [:@@var1]
3692 * Two.class_variables #=> [:@@var2, :@@var1]
3693 * Two.class_variables(false) #=> [:@@var2]
3696 VALUE
3697 rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
3699 bool inherit = true;
3700 st_table *tbl;
3702 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3703 if (inherit) {
3704 tbl = mod_cvar_of(mod, 0);
3706 else {
3707 tbl = mod_cvar_at(mod, 0);
3709 return cvar_list(tbl);
3713 * call-seq:
3714 * remove_class_variable(sym) -> obj
3716 * Removes the named class variable from the receiver, returning that
3717 * variable's value.
3719 * class Example
3720 * @@var = 99
3721 * puts remove_class_variable(:@@var)
3722 * p(defined? @@var)
3723 * end
3725 * <em>produces:</em>
3727 * 99
3728 * nil
3731 VALUE
3732 rb_mod_remove_cvar(VALUE mod, VALUE name)
3734 const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
3735 st_data_t val, n = id;
3737 if (!id) {
3738 goto not_defined;
3740 rb_check_frozen(mod);
3741 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
3742 return (VALUE)val;
3744 if (rb_cvar_defined(mod, id)) {
3745 rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
3747 not_defined:
3748 rb_name_err_raise("class variable %1$s not defined for %2$s",
3749 mod, name);
3750 UNREACHABLE_RETURN(Qundef);
3753 VALUE
3754 rb_iv_get(VALUE obj, const char *name)
3756 ID id = rb_check_id_cstr(name, strlen(name), rb_usascii_encoding());
3758 if (!id) {
3759 return Qnil;
3761 return rb_ivar_get(obj, id);
3764 VALUE
3765 rb_iv_set(VALUE obj, const char *name, VALUE val)
3767 ID id = rb_intern(name);
3769 return rb_ivar_set(obj, id, val);
3772 /* tbl = xx(obj); tbl[key] = value; */
3774 rb_class_ivar_set(VALUE obj, ID key, VALUE value)
3776 if (!RCLASS_IV_TBL(obj)) {
3777 RCLASS_IV_TBL(obj) = st_init_numtable();
3780 st_table *tbl = RCLASS_IV_TBL(obj);
3781 int result = lock_st_insert(tbl, (st_data_t)key, (st_data_t)value);
3782 RB_OBJ_WRITTEN(obj, Qundef, value);
3783 return result;
3786 static int
3787 tbl_copy_i(st_data_t key, st_data_t value, st_data_t data)
3789 RB_OBJ_WRITTEN((VALUE)data, Qundef, (VALUE)value);
3790 return ST_CONTINUE;
3793 void
3794 rb_iv_tbl_copy(VALUE dst, VALUE src)
3796 st_table *orig_tbl = RCLASS_IV_TBL(src);
3797 st_table *new_tbl = st_copy(orig_tbl);
3798 st_foreach(new_tbl, tbl_copy_i, (st_data_t)dst);
3799 RCLASS_IV_TBL(dst) = new_tbl;
3802 MJIT_FUNC_EXPORTED rb_const_entry_t *
3803 rb_const_lookup(VALUE klass, ID id)
3805 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3807 if (tbl) {
3808 VALUE val;
3809 bool r;
3810 RB_VM_LOCK_ENTER();
3812 r = rb_id_table_lookup(tbl, id, &val);
3814 RB_VM_LOCK_LEAVE();
3816 if (r) return (rb_const_entry_t *)val;
3818 return NULL;