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