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