Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
variable.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
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_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  rb_raise(rb_eRactorUnsafeError, "require by autoload on non-main Ractor is not supported (%s)", rb_id2name(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 
3284 
3285  val = ce->value;
3286 
3287  if (UNDEF_P(val)) {
3288  autoload_delete(mod, id);
3289  val = Qnil;
3290  }
3291 
3292  ruby_xfree(ce);
3293 
3294  return val;
3295 }
3296 
3297 static int
3298 cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
3299 {
3300  if (existing) return ST_STOP;
3301  *v = a;
3302  return ST_CONTINUE;
3303 }
3304 
3305 static enum rb_id_table_iterator_result
3306 sv_i(ID key, VALUE v, void *a)
3307 {
3309  st_table *tbl = a;
3310 
3311  if (rb_is_const_id(key)) {
3312  st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
3313  }
3314  return ID_TABLE_CONTINUE;
3315 }
3316 
3317 static enum rb_id_table_iterator_result
3318 rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
3319 {
3320  if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
3321  rb_ary_push((VALUE)ary, ID2SYM(const_name));
3322  }
3323  return ID_TABLE_CONTINUE;
3324 }
3325 
3326 static VALUE
3327 rb_local_constants(VALUE mod)
3328 {
3329  struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
3330  VALUE ary;
3331 
3332  if (!tbl) return rb_ary_new2(0);
3333 
3334  RB_VM_LOCK_ENTER();
3335  {
3336  ary = rb_ary_new2(rb_id_table_size(tbl));
3337  rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
3338  }
3339  RB_VM_LOCK_LEAVE();
3340 
3341  return ary;
3342 }
3343 
3344 void*
3345 rb_mod_const_at(VALUE mod, void *data)
3346 {
3347  st_table *tbl = data;
3348  if (!tbl) {
3349  tbl = st_init_numtable();
3350  }
3351  if (RCLASS_CONST_TBL(mod)) {
3352  RB_VM_LOCK_ENTER();
3353  {
3354  rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
3355  }
3356  RB_VM_LOCK_LEAVE();
3357  }
3358  return tbl;
3359 }
3360 
3361 void*
3362 rb_mod_const_of(VALUE mod, void *data)
3363 {
3364  VALUE tmp = mod;
3365  for (;;) {
3366  data = rb_mod_const_at(tmp, data);
3367  tmp = RCLASS_SUPER(tmp);
3368  if (!tmp) break;
3369  if (tmp == rb_cObject && mod != rb_cObject) break;
3370  }
3371  return data;
3372 }
3373 
3374 static int
3375 list_i(st_data_t key, st_data_t value, VALUE ary)
3376 {
3377  ID sym = (ID)key;
3378  rb_const_entry_t *ce = (rb_const_entry_t *)value;
3379  if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
3380  return ST_CONTINUE;
3381 }
3382 
3383 VALUE
3384 rb_const_list(void *data)
3385 {
3386  st_table *tbl = data;
3387  VALUE ary;
3388 
3389  if (!tbl) return rb_ary_new2(0);
3390  ary = rb_ary_new2(tbl->num_entries);
3391  st_foreach_safe(tbl, list_i, ary);
3392  st_free_table(tbl);
3393 
3394  return ary;
3395 }
3396 
3397 /*
3398  * call-seq:
3399  * mod.constants(inherit=true) -> array
3400  *
3401  * Returns an array of the names of the constants accessible in
3402  * <i>mod</i>. This includes the names of constants in any included
3403  * modules (example at start of section), unless the <i>inherit</i>
3404  * parameter is set to <code>false</code>.
3405  *
3406  * The implementation makes no guarantees about the order in which the
3407  * constants are yielded.
3408  *
3409  * IO.constants.include?(:SYNC) #=> true
3410  * IO.constants(false).include?(:SYNC) #=> false
3411  *
3412  * Also see Module#const_defined?.
3413  */
3414 
3415 VALUE
3416 rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
3417 {
3418  bool inherit = true;
3419 
3420  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3421 
3422  if (inherit) {
3423  return rb_const_list(rb_mod_const_of(mod, 0));
3424  }
3425  else {
3426  return rb_local_constants(mod);
3427  }
3428 }
3429 
3430 static int
3431 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
3432 {
3433  VALUE tmp;
3434  int mod_retry = 0;
3435  rb_const_entry_t *ce;
3436 
3437  tmp = klass;
3438  retry:
3439  while (tmp) {
3440  if ((ce = rb_const_lookup(tmp, id))) {
3441  if (visibility && RB_CONST_PRIVATE_P(ce)) {
3442  return (int)Qfalse;
3443  }
3444  if (UNDEF_P(ce->value) && !check_autoload_required(tmp, id, 0) &&
3445  !rb_autoloading_value(tmp, id, NULL, NULL))
3446  return (int)Qfalse;
3447 
3448  if (exclude && tmp == rb_cObject && klass != rb_cObject) {
3449  return (int)Qfalse;
3450  }
3451 
3452  return (int)Qtrue;
3453  }
3454  if (!recurse) break;
3455  tmp = RCLASS_SUPER(tmp);
3456  }
3457  if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
3458  mod_retry = 1;
3459  tmp = rb_cObject;
3460  goto retry;
3461  }
3462  return (int)Qfalse;
3463 }
3464 
3465 int
3467 {
3468  return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
3469 }
3470 
3471 int
3473 {
3474  return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
3475 }
3476 
3477 int
3479 {
3480  return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
3481 }
3482 
3483 int
3484 rb_public_const_defined_from(VALUE klass, ID id)
3485 {
3486  return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
3487 }
3488 
3489 static void
3490 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
3491 {
3492  rb_check_frozen(klass);
3493 }
3494 
3495 static void set_namespace_path(VALUE named_namespace, VALUE name);
3496 
3497 static enum rb_id_table_iterator_result
3498 set_namespace_path_i(ID id, VALUE v, void *payload)
3499 {
3501  VALUE value = ce->value;
3502  VALUE parental_path = *((VALUE *) payload);
3503  if (!rb_is_const_id(id) || !rb_namespace_p(value)) {
3504  return ID_TABLE_CONTINUE;
3505  }
3506 
3507  bool has_permanent_classpath;
3508  classname(value, &has_permanent_classpath);
3509  if (has_permanent_classpath) {
3510  return ID_TABLE_CONTINUE;
3511  }
3512  set_namespace_path(value, build_const_path(parental_path, id));
3513 
3514  if (!RCLASS_EXT(value)->permanent_classpath) {
3515  RCLASS_SET_CLASSPATH(value, 0, false);
3516  }
3517 
3518  return ID_TABLE_CONTINUE;
3519 }
3520 
3521 /*
3522  * Assign permanent classpaths to all namespaces that are directly or indirectly
3523  * nested under +named_namespace+. +named_namespace+ must have a permanent
3524  * classpath.
3525  */
3526 static void
3527 set_namespace_path(VALUE named_namespace, VALUE namespace_path)
3528 {
3529  struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
3530 
3531  RB_VM_LOCK_ENTER();
3532  {
3533  RCLASS_SET_CLASSPATH(named_namespace, namespace_path, true);
3534 
3535  if (const_table) {
3536  rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
3537  }
3538  }
3539  RB_VM_LOCK_LEAVE();
3540 }
3541 
3542 static void
3543 const_added(VALUE klass, ID const_name)
3544 {
3545  if (GET_VM()->running) {
3546  VALUE name = ID2SYM(const_name);
3547  rb_funcallv(klass, idConst_added, 1, &name);
3548  }
3549 }
3550 
3551 static void
3552 const_set(VALUE klass, ID id, VALUE val)
3553 {
3554  rb_const_entry_t *ce;
3555 
3556  if (NIL_P(klass)) {
3557  rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
3558  QUOTE_ID(id));
3559  }
3560 
3561  if (!rb_ractor_main_p() && !rb_ractor_shareable_p(val)) {
3562  rb_raise(rb_eRactorIsolationError, "can not set constants with non-shareable objects by non-main Ractors");
3563  }
3564 
3565  check_before_mod_set(klass, id, val, "constant");
3566 
3567  RB_VM_LOCK_ENTER();
3568  {
3569  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3570  if (!tbl) {
3571  RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
3573  ce = ZALLOC(rb_const_entry_t);
3574  rb_id_table_insert(tbl, id, (VALUE)ce);
3575  setup_const_entry(ce, klass, val, CONST_PUBLIC);
3576  }
3577  else {
3578  struct autoload_const ac = {
3579  .module = klass, .name = id,
3580  .value = val, .flag = CONST_PUBLIC,
3581  /* fill the rest with 0 */
3582  };
3583  ac.file = rb_source_location(&ac.line);
3584  const_tbl_update(&ac, false);
3585  }
3586  }
3587  RB_VM_LOCK_LEAVE();
3588 
3589  /*
3590  * Resolve and cache class name immediately to resolve ambiguity
3591  * and avoid order-dependency on const_tbl
3592  */
3593  if (rb_cObject && rb_namespace_p(val)) {
3594  bool val_path_permanent;
3595  VALUE val_path = classname(val, &val_path_permanent);
3596  if (NIL_P(val_path) || !val_path_permanent) {
3597  if (klass == rb_cObject) {
3598  set_namespace_path(val, rb_id2str(id));
3599  }
3600  else {
3601  bool parental_path_permanent;
3602  VALUE parental_path = classname(klass, &parental_path_permanent);
3603  if (NIL_P(parental_path)) {
3604  bool throwaway;
3605  parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
3606  }
3607  if (parental_path_permanent && !val_path_permanent) {
3608  set_namespace_path(val, build_const_path(parental_path, id));
3609  }
3610  else if (!parental_path_permanent && NIL_P(val_path)) {
3611  RCLASS_SET_CLASSPATH(val, build_const_path(parental_path, id), false);
3612  }
3613  }
3614  }
3615  }
3616 }
3617 
3618 void
3619 rb_const_set(VALUE klass, ID id, VALUE val)
3620 {
3621  const_set(klass, id, val);
3622  const_added(klass, id);
3623 }
3624 
3625 static struct autoload_data *
3626 autoload_data_for_named_constant(VALUE module, ID name, struct autoload_const **autoload_const_pointer)
3627 {
3628  VALUE autoload_data_value = autoload_data(module, name);
3629  if (!autoload_data_value) return 0;
3630 
3631  struct autoload_data *autoload_data = get_autoload_data(autoload_data_value, autoload_const_pointer);
3632  if (!autoload_data) return 0;
3633 
3634  /* for autoloading thread, keep the defined value to autoloading storage */
3635  if (autoload_by_current(autoload_data)) {
3636  return autoload_data;
3637  }
3638 
3639  return 0;
3640 }
3641 
3642 static void
3643 const_tbl_update(struct autoload_const *ac, int autoload_force)
3644 {
3645  VALUE value;
3646  VALUE klass = ac->module;
3647  VALUE val = ac->value;
3648  ID id = ac->name;
3649  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3650  rb_const_flag_t visibility = ac->flag;
3651  rb_const_entry_t *ce;
3652 
3653  if (rb_id_table_lookup(tbl, id, &value)) {
3654  ce = (rb_const_entry_t *)value;
3655  if (UNDEF_P(ce->value)) {
3656  RUBY_ASSERT_CRITICAL_SECTION_ENTER();
3657  VALUE file = ac->file;
3658  int line = ac->line;
3659  struct autoload_data *ele = autoload_data_for_named_constant(klass, id, &ac);
3660 
3661  if (!autoload_force && ele) {
3663 
3664  ac->value = val; /* autoload_data is non-WB-protected */
3665  ac->file = rb_source_location(&ac->line);
3666  }
3667  else {
3668  /* otherwise autoloaded constant, allow to override */
3669  autoload_delete(klass, id);
3670  ce->flag = visibility;
3671  RB_OBJ_WRITE(klass, &ce->value, val);
3672  RB_OBJ_WRITE(klass, &ce->file, file);
3673  ce->line = line;
3674  }
3675  RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
3676  return;
3677  }
3678  else {
3679  VALUE name = QUOTE_ID(id);
3680  visibility = ce->flag;
3681  if (klass == rb_cObject)
3682  rb_warn("already initialized constant %"PRIsVALUE"", name);
3683  else
3684  rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
3685  rb_class_name(klass), name);
3686  if (!NIL_P(ce->file) && ce->line) {
3687  rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
3688  "previous definition of %"PRIsVALUE" was here", name);
3689  }
3690  }
3692  setup_const_entry(ce, klass, val, visibility);
3693  }
3694  else {
3696 
3697  ce = ZALLOC(rb_const_entry_t);
3698  rb_id_table_insert(tbl, id, (VALUE)ce);
3699  setup_const_entry(ce, klass, val, visibility);
3700  }
3701 }
3702 
3703 static void
3704 setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
3705  rb_const_flag_t visibility)
3706 {
3707  ce->flag = visibility;
3708  RB_OBJ_WRITE(klass, &ce->value, val);
3709  RB_OBJ_WRITE(klass, &ce->file, rb_source_location(&ce->line));
3710 }
3711 
3712 void
3713 rb_define_const(VALUE klass, const char *name, VALUE val)
3714 {
3715  ID id = rb_intern(name);
3716 
3717  if (!rb_is_const_id(id)) {
3718  rb_warn("rb_define_const: invalid name '%s' for constant", name);
3719  }
3720  if (!RB_SPECIAL_CONST_P(val)) {
3721  rb_vm_register_global_object(val);
3722  }
3723  rb_const_set(klass, id, val);
3724 }
3725 
3726 void
3727 rb_define_global_const(const char *name, VALUE val)
3728 {
3729  rb_define_const(rb_cObject, name, val);
3730 }
3731 
3732 static void
3733 set_const_visibility(VALUE mod, int argc, const VALUE *argv,
3734  rb_const_flag_t flag, rb_const_flag_t mask)
3735 {
3736  int i;
3737  rb_const_entry_t *ce;
3738  ID id;
3739 
3740  rb_class_modify_check(mod);
3741  if (argc == 0) {
3742  rb_warning("%"PRIsVALUE" with no argument is just ignored",
3743  QUOTE_ID(rb_frame_callee()));
3744  return;
3745  }
3746 
3747  for (i = 0; i < argc; i++) {
3748  struct autoload_const *ac;
3749  VALUE val = argv[i];
3750  id = rb_check_id(&val);
3751  if (!id) {
3752  undefined_constant(mod, val);
3753  }
3754  if ((ce = rb_const_lookup(mod, id))) {
3755  ce->flag &= ~mask;
3756  ce->flag |= flag;
3757  if (UNDEF_P(ce->value)) {
3758  struct autoload_data *ele;
3759 
3760  ele = autoload_data_for_named_constant(mod, id, &ac);
3761  if (ele) {
3762  ac->flag &= ~mask;
3763  ac->flag |= flag;
3764  }
3765  }
3767  }
3768  else {
3769  undefined_constant(mod, ID2SYM(id));
3770  }
3771  }
3772 }
3773 
3774 void
3775 rb_deprecate_constant(VALUE mod, const char *name)
3776 {
3777  rb_const_entry_t *ce;
3778  ID id;
3779  long len = strlen(name);
3780 
3781  rb_class_modify_check(mod);
3782  if (!(id = rb_check_id_cstr(name, len, NULL))) {
3783  undefined_constant(mod, rb_fstring_new(name, len));
3784  }
3785  if (!(ce = rb_const_lookup(mod, id))) {
3786  undefined_constant(mod, ID2SYM(id));
3787  }
3788  ce->flag |= CONST_DEPRECATED;
3789 }
3790 
3791 /*
3792  * call-seq:
3793  * mod.private_constant(symbol, ...) => mod
3794  *
3795  * Makes a list of existing constants private.
3796  */
3797 
3798 VALUE
3799 rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
3800 {
3801  set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
3802  return obj;
3803 }
3804 
3805 /*
3806  * call-seq:
3807  * mod.public_constant(symbol, ...) => mod
3808  *
3809  * Makes a list of existing constants public.
3810  */
3811 
3812 VALUE
3813 rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
3814 {
3815  set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
3816  return obj;
3817 }
3818 
3819 /*
3820  * call-seq:
3821  * mod.deprecate_constant(symbol, ...) => mod
3822  *
3823  * Makes a list of existing constants deprecated. Attempt
3824  * to refer to them will produce a warning.
3825  *
3826  * module HTTP
3827  * NotFound = Exception.new
3828  * NOT_FOUND = NotFound # previous version of the library used this name
3829  *
3830  * deprecate_constant :NOT_FOUND
3831  * end
3832  *
3833  * HTTP::NOT_FOUND
3834  * # warning: constant HTTP::NOT_FOUND is deprecated
3835  *
3836  */
3837 
3838 VALUE
3839 rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
3840 {
3841  set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3842  return obj;
3843 }
3844 
3845 static VALUE
3846 original_module(VALUE c)
3847 {
3848  if (RB_TYPE_P(c, T_ICLASS))
3849  return RBASIC(c)->klass;
3850  return c;
3851 }
3852 
3853 static int
3854 cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3855 {
3856  if (RB_TYPE_P(klass, T_ICLASS)) {
3857  if (FL_TEST_RAW(klass, RICLASS_IS_ORIGIN)) {
3858  return 0;
3859  }
3860  else {
3861  // check the original module
3862  klass = RBASIC(klass)->klass;
3863  }
3864  }
3865 
3866  VALUE n = rb_ivar_lookup(klass, id, Qundef);
3867  if (UNDEF_P(n)) return 0;
3868 
3869  if (v) *v = n;
3870  return 1;
3871 }
3872 
3873 static VALUE
3874 cvar_front_klass(VALUE klass)
3875 {
3876  if (RCLASS_SINGLETON_P(klass)) {
3877  VALUE obj = RCLASS_ATTACHED_OBJECT(klass);
3878  if (rb_namespace_p(obj)) {
3879  return obj;
3880  }
3881  }
3882  return RCLASS_SUPER(klass);
3883 }
3884 
3885 static void
3886 cvar_overtaken(VALUE front, VALUE target, ID id)
3887 {
3888  if (front && target != front) {
3889  if (original_module(front) != original_module(target)) {
3891  "class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3892  ID2SYM(id), rb_class_name(original_module(front)),
3893  rb_class_name(original_module(target)));
3894  }
3895  if (BUILTIN_TYPE(front) == T_CLASS) {
3896  rb_ivar_delete(front, id, Qundef);
3897  }
3898  }
3899 }
3900 
3901 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3902  for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3903  if (cvar_lookup_at(klass, id, (v))) { \
3904  r; \
3905  } \
3906  }
3907 
3908 #define CVAR_LOOKUP(v,r) do {\
3909  CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
3910  if (cvar_lookup_at(klass, id, (v))) {r;}\
3911  CVAR_FOREACH_ANCESTORS(klass, v, r);\
3912 } while(0)
3913 
3914 static VALUE
3915 find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id)
3916 {
3917  VALUE v = Qundef;
3918  CVAR_LOOKUP(&v, {
3919  if (!*front) {
3920  *front = klass;
3921  }
3922  *target = klass;
3923  });
3924 
3925  return v;
3926 }
3927 
3928 static void
3929 check_for_cvar_table(VALUE subclass, VALUE key)
3930 {
3931  // Must not check ivar on ICLASS
3932  if (!RB_TYPE_P(subclass, T_ICLASS) && RTEST(rb_ivar_defined(subclass, key))) {
3933  RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
3934  ruby_vm_global_cvar_state++;
3935  return;
3936  }
3937 
3938  rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
3939 }
3940 
3941 void
3942 rb_cvar_set(VALUE klass, ID id, VALUE val)
3943 {
3944  VALUE tmp, front = 0, target = 0;
3945 
3946  tmp = klass;
3947  CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3948  if (target) {
3949  cvar_overtaken(front, target, id);
3950  }
3951  else {
3952  target = tmp;
3953  }
3954 
3955  if (RB_TYPE_P(target, T_ICLASS)) {
3956  target = RBASIC(target)->klass;
3957  }
3958  check_before_mod_set(target, id, val, "class variable");
3959 
3960  int result = rb_class_ivar_set(target, id, val);
3961 
3962  struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
3963 
3964  if (!rb_cvc_tbl) {
3965  rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
3966  }
3967 
3968  struct rb_cvar_class_tbl_entry *ent;
3969  VALUE ent_data;
3970 
3971  if (!rb_id_table_lookup(rb_cvc_tbl, id, &ent_data)) {
3972  ent = ALLOC(struct rb_cvar_class_tbl_entry);
3973  ent->class_value = target;
3974  ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3975  ent->cref = 0;
3976  rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent);
3977  RB_DEBUG_COUNTER_INC(cvar_inline_miss);
3978  }
3979  else {
3980  ent = (void *)ent_data;
3981  ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
3982  }
3983 
3984  // Break the cvar cache if this is a new class variable
3985  // and target is a module or a subclass with the same
3986  // cvar in this lookup.
3987  if (result == 0) {
3988  if (RB_TYPE_P(target, T_CLASS)) {
3989  if (RCLASS_SUBCLASSES(target)) {
3990  rb_class_foreach_subclass(target, check_for_cvar_table, id);
3991  }
3992  }
3993  }
3994 }
3995 
3996 VALUE
3997 rb_cvar_find(VALUE klass, ID id, VALUE *front)
3998 {
3999  VALUE target = 0;
4000  VALUE value;
4001 
4002  value = find_cvar(klass, front, &target, id);
4003  if (!target) {
4004  rb_name_err_raise("uninitialized class variable %1$s in %2$s",
4005  klass, ID2SYM(id));
4006  }
4007  cvar_overtaken(*front, target, id);
4008  return (VALUE)value;
4009 }
4010 
4011 VALUE
4013 {
4014  VALUE front = 0;
4015  return rb_cvar_find(klass, id, &front);
4016 }
4017 
4018 VALUE
4020 {
4021  if (!klass) return Qfalse;
4022  CVAR_LOOKUP(0,return Qtrue);
4023  return Qfalse;
4024 }
4025 
4026 static ID
4027 cv_intern(VALUE klass, const char *name)
4028 {
4029  ID id = rb_intern(name);
4030  if (!rb_is_class_id(id)) {
4031  rb_name_err_raise("wrong class variable name %1$s",
4032  klass, rb_str_new_cstr(name));
4033  }
4034  return id;
4035 }
4036 
4037 void
4038 rb_cv_set(VALUE klass, const char *name, VALUE val)
4039 {
4040  ID id = cv_intern(klass, name);
4041  rb_cvar_set(klass, id, val);
4042 }
4043 
4044 VALUE
4045 rb_cv_get(VALUE klass, const char *name)
4046 {
4047  ID id = cv_intern(klass, name);
4048  return rb_cvar_get(klass, id);
4049 }
4050 
4051 void
4052 rb_define_class_variable(VALUE klass, const char *name, VALUE val)
4053 {
4054  rb_cv_set(klass, name, val);
4055 }
4056 
4057 static int
4058 cv_i(ID key, VALUE v, st_data_t a)
4059 {
4060  st_table *tbl = (st_table *)a;
4061 
4062  if (rb_is_class_id(key)) {
4063  st_update(tbl, (st_data_t)key, cv_i_update, 0);
4064  }
4065  return ST_CONTINUE;
4066 }
4067 
4068 static void*
4069 mod_cvar_at(VALUE mod, void *data)
4070 {
4071  st_table *tbl = data;
4072  if (!tbl) {
4073  tbl = st_init_numtable();
4074  }
4075  mod = original_module(mod);
4076 
4077  rb_ivar_foreach(mod, cv_i, (st_data_t)tbl);
4078  return tbl;
4079 }
4080 
4081 static void*
4082 mod_cvar_of(VALUE mod, void *data)
4083 {
4084  VALUE tmp = mod;
4085  if (RCLASS_SINGLETON_P(mod)) {
4086  if (rb_namespace_p(RCLASS_ATTACHED_OBJECT(mod))) {
4087  data = mod_cvar_at(tmp, data);
4088  tmp = cvar_front_klass(tmp);
4089  }
4090  }
4091  for (;;) {
4092  data = mod_cvar_at(tmp, data);
4093  tmp = RCLASS_SUPER(tmp);
4094  if (!tmp) break;
4095  }
4096  return data;
4097 }
4098 
4099 static int
4100 cv_list_i(st_data_t key, st_data_t value, VALUE ary)
4101 {
4102  ID sym = (ID)key;
4103  rb_ary_push(ary, ID2SYM(sym));
4104  return ST_CONTINUE;
4105 }
4106 
4107 static VALUE
4108 cvar_list(void *data)
4109 {
4110  st_table *tbl = data;
4111  VALUE ary;
4112 
4113  if (!tbl) return rb_ary_new2(0);
4114  ary = rb_ary_new2(tbl->num_entries);
4115  st_foreach_safe(tbl, cv_list_i, ary);
4116  st_free_table(tbl);
4117 
4118  return ary;
4119 }
4120 
4121 /*
4122  * call-seq:
4123  * mod.class_variables(inherit=true) -> array
4124  *
4125  * Returns an array of the names of class variables in <i>mod</i>.
4126  * This includes the names of class variables in any included
4127  * modules, unless the <i>inherit</i> parameter is set to
4128  * <code>false</code>.
4129  *
4130  * class One
4131  * @@var1 = 1
4132  * end
4133  * class Two < One
4134  * @@var2 = 2
4135  * end
4136  * One.class_variables #=> [:@@var1]
4137  * Two.class_variables #=> [:@@var2, :@@var1]
4138  * Two.class_variables(false) #=> [:@@var2]
4139  */
4140 
4141 VALUE
4142 rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
4143 {
4144  bool inherit = true;
4145  st_table *tbl;
4146 
4147  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
4148  if (inherit) {
4149  tbl = mod_cvar_of(mod, 0);
4150  }
4151  else {
4152  tbl = mod_cvar_at(mod, 0);
4153  }
4154  return cvar_list(tbl);
4155 }
4156 
4157 /*
4158  * call-seq:
4159  * remove_class_variable(sym) -> obj
4160  *
4161  * Removes the named class variable from the receiver, returning that
4162  * variable's value.
4163  *
4164  * class Example
4165  * @@var = 99
4166  * puts remove_class_variable(:@@var)
4167  * p(defined? @@var)
4168  * end
4169  *
4170  * <em>produces:</em>
4171  *
4172  * 99
4173  * nil
4174  */
4175 
4176 VALUE
4178 {
4179  const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
4180  st_data_t val;
4181 
4182  if (!id) {
4183  goto not_defined;
4184  }
4185  rb_check_frozen(mod);
4186  val = rb_ivar_delete(mod, id, Qundef);
4187  if (!UNDEF_P(val)) {
4188  return (VALUE)val;
4189  }
4190  if (rb_cvar_defined(mod, id)) {
4191  rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
4192  }
4193  not_defined:
4194  rb_name_err_raise("class variable %1$s not defined for %2$s",
4195  mod, name);
4197 }
4198 
4199 VALUE
4200 rb_iv_get(VALUE obj, const char *name)
4201 {
4202  ID id = rb_check_id_cstr(name, strlen(name), rb_usascii_encoding());
4203 
4204  if (!id) {
4205  return Qnil;
4206  }
4207  return rb_ivar_get(obj, id);
4208 }
4209 
4210 VALUE
4211 rb_iv_set(VALUE obj, const char *name, VALUE val)
4212 {
4213  ID id = rb_intern(name);
4214 
4215  return rb_ivar_set(obj, id, val);
4216 }
4217 
4218 static VALUE *
4219 class_ivar_set_shape_ivptr(VALUE obj, void *_data)
4220 {
4221  RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
4222 
4223  return RCLASS_IVPTR(obj);
4224 }
4225 
4226 static void
4227 class_ivar_set_shape_resize_ivptr(VALUE obj, attr_index_t _old_capa, attr_index_t new_capa, void *_data)
4228 {
4229  REALLOC_N(RCLASS_IVPTR(obj), VALUE, new_capa);
4230 }
4231 
4232 static void
4233 class_ivar_set_set_shape(VALUE obj, rb_shape_t *shape, void *_data)
4234 {
4235  rb_shape_set_shape(obj, shape);
4236 }
4237 
4238 static void
4239 class_ivar_set_transition_too_complex(VALUE obj, void *_data)
4240 {
4241  rb_evict_ivars_to_hash(obj);
4242 }
4243 
4244 static st_table *
4245 class_ivar_set_too_complex_table(VALUE obj, void *_data)
4246 {
4247  RUBY_ASSERT(rb_shape_obj_too_complex(obj));
4248 
4249  return RCLASS_IV_HASH(obj);
4250 }
4251 
4252 int
4253 rb_class_ivar_set(VALUE obj, ID id, VALUE val)
4254 {
4256  bool existing = false;
4257  rb_check_frozen(obj);
4258 
4259  RB_VM_LOCK_ENTER();
4260  {
4261  existing = general_ivar_set(obj, id, val, NULL,
4262  class_ivar_set_shape_ivptr,
4263  class_ivar_set_shape_resize_ivptr,
4264  class_ivar_set_set_shape,
4265  class_ivar_set_transition_too_complex,
4266  class_ivar_set_too_complex_table).existing;
4267  }
4268  RB_VM_LOCK_LEAVE();
4269 
4270  return existing;
4271 }
4272 
4273 static int
4274 tbl_copy_i(ID key, VALUE val, st_data_t dest)
4275 {
4276  rb_class_ivar_set((VALUE)dest, key, val);
4277 
4278  return ST_CONTINUE;
4279 }
4280 
4281 void
4282 rb_iv_tbl_copy(VALUE dst, VALUE src)
4283 {
4284  RUBY_ASSERT(rb_type(dst) == rb_type(src));
4286 
4287  RUBY_ASSERT(rb_shape_get_shape(dst)->type == SHAPE_ROOT);
4288  RUBY_ASSERT(!RCLASS_IVPTR(dst));
4289 
4290  rb_ivar_foreach(src, tbl_copy_i, dst);
4291 }
4292 
4294 rb_const_lookup(VALUE klass, ID id)
4295 {
4296  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
4297 
4298  if (tbl) {
4299  VALUE val;
4300  bool r;
4301  RB_VM_LOCK_ENTER();
4302  {
4303  r = rb_id_table_lookup(tbl, id, &val);
4304  }
4305  RB_VM_LOCK_LEAVE();
4306 
4307  if (r) return (rb_const_entry_t *)val;
4308  }
4309  return NULL;
4310 }
#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 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:1370
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:475
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
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:396
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:1088
void rb_name_error(ID id, const char *fmt,...)
Raises an instance of rb_eNameError.
Definition: error.c:2210
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1403
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:2225
VALUE rb_eNameError
NameError exception.
Definition: error.c:1408
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1401
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
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:496
@ 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:1472
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:1013
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:2410
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:2076
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:2106
VALUE rb_gc_location(VALUE obj)
Finds a new "location" of an object.
Definition: gc.c:3004
void rb_gc_update_tbl_refs(st_table *ptr)
Updates references inside of tables.
Definition: gc.c:2966
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:686
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
Definition: vm.c:1817
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:3662
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:3046
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition: string.c:1446
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:1911
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:1054
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:4177
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:3384
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:3345
void rb_cvar_set(VALUE klass, ID name, VALUE val)
Assigns a value to a class variable.
Definition: variable.c:3942
VALUE rb_cvar_get(VALUE klass, ID name)
Obtains a value from a class variable.
Definition: variable.c:4012
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv)
Resembles Module#constants.
Definition: variable.c:3416
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front)
Identical to rb_cvar_get(), except it takes additional "front" pointer.
Definition: variable.c:3997
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:3619
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:4052
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:4045
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:3478
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:4038
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv)
Resembles Module#class_variables.
Definition: variable.c:4142
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:4019
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:3466
void * rb_mod_const_of(VALUE, void *)
This is a variant of rb_mod_const_at().
Definition: variable.c:3362
int rb_const_defined(VALUE space, ID name)
Queries if the constant is defined at the namespace.
Definition: variable.c:3472
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:1854
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:2032
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:12450
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:3727
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:3775
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:3713
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:4200
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:4211
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:4264