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