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