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