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