Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
variable.c
Go to the documentation of this file.
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/encoding.h"
15 #include "ruby/st.h"
16 #include "ruby/util.h"
17 #include "internal.h"
18 #include "id_table.h"
19 #include "constant.h"
20 #include "id.h"
21 #include "ccan/list/list.h"
22 #include "id_table.h"
23 #include "debug_counter.h"
24 #include "vm_core.h"
25 #include "transient_heap.h"
26 #include "variable.h"
27 
28 static struct rb_id_table *rb_global_tbl;
29 static ID autoload, classpath, tmp_classpath;
30 static VALUE autoload_featuremap; /* feature => autoload_i */
31 
32 static void check_before_mod_set(VALUE, ID, VALUE, const char *);
33 static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
34 static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
35 static st_table *generic_iv_tbl;
36 static st_table *generic_iv_tbl_compat;
37 
38 struct ivar_update {
39  union {
41  struct gen_ivtbl *ivtbl;
42  } u;
45 };
46 
47 void
49 {
50  rb_global_tbl = rb_id_table_create(0);
51  generic_iv_tbl = st_init_numtable();
52  autoload = rb_intern_const("__autoload__");
53  /* __classpath__: fully qualified class path */
54  classpath = rb_intern_const("__classpath__");
55  /* __tmp_classpath__: temporary class path which contains anonymous names */
56  tmp_classpath = rb_intern_const("__tmp_classpath__");
57 }
58 
59 static inline bool
60 rb_namespace_p(VALUE obj)
61 {
62  if (RB_SPECIAL_CONST_P(obj)) return false;
63  switch (RB_BUILTIN_TYPE(obj)) {
64  case T_MODULE: case T_CLASS: return true;
65  }
66  return false;
67 }
68 
77 static VALUE
78 classname(VALUE klass, int *permanent)
79 {
80  st_table *ivtbl;
81  st_data_t n;
82 
83  *permanent = 0;
84  if (!RCLASS_EXT(klass)) return Qnil;
85  if (!(ivtbl = RCLASS_IV_TBL(klass))) return Qnil;
86  if (st_lookup(ivtbl, (st_data_t)classpath, &n)) {
87  *permanent = 1;
88  return (VALUE)n;
89  }
90  if (st_lookup(ivtbl, (st_data_t)tmp_classpath, &n)) return (VALUE)n;
91  return Qnil;
92 }
93 
94 /*
95  * call-seq:
96  * mod.name -> string
97  *
98  * Returns the name of the module <i>mod</i>. Returns nil for anonymous modules.
99  */
100 
101 VALUE
103 {
104  int permanent;
105  return classname(mod, &permanent);
106 }
107 
108 static VALUE
109 make_temporary_path(VALUE obj, VALUE klass)
110 {
111  VALUE path;
112  switch (klass) {
113  case Qnil:
114  path = rb_sprintf("#<Class:%p>", (void*)obj);
115  break;
116  case Qfalse:
117  path = rb_sprintf("#<Module:%p>", (void*)obj);
118  break;
119  default:
120  path = rb_sprintf("#<%"PRIsVALUE":%p>", klass, (void*)obj);
121  break;
122  }
123  OBJ_FREEZE(path);
124  return path;
125 }
126 
128 
129 static VALUE
130 rb_tmp_class_path(VALUE klass, int *permanent, fallback_func fallback)
131 {
132  VALUE path = classname(klass, permanent);
133 
134  if (!NIL_P(path)) {
135  return path;
136  }
137  else {
138  if (RB_TYPE_P(klass, T_MODULE)) {
139  if (rb_obj_class(klass) == rb_cModule) {
140  path = Qfalse;
141  }
142  else {
143  int perm;
144  path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, fallback);
145  }
146  }
147  *permanent = 0;
148  return fallback(klass, path);
149  }
150 }
151 
152 VALUE
154 {
155  int permanent;
156  VALUE path = rb_tmp_class_path(klass, &permanent, make_temporary_path);
157  if (!NIL_P(path)) path = rb_str_dup(path);
158  return path;
159 }
160 
161 VALUE
163 {
164  int permanent;
165  return classname(klass, &permanent);
166 }
167 
168 static VALUE
169 no_fallback(VALUE obj, VALUE name)
170 {
171  return name;
172 }
173 
174 VALUE
176 {
177  int permanent;
178  return rb_tmp_class_path(klass, &permanent, no_fallback);
179 }
180 
181 static VALUE
182 build_const_pathname(VALUE head, VALUE tail)
183 {
184  VALUE path = rb_str_dup(head);
185  rb_str_cat2(path, "::");
186  rb_str_append(path, tail);
187  OBJ_FREEZE(path);
188  return path;
189 }
190 
191 static VALUE
192 build_const_path(VALUE head, ID tail)
193 {
194  return build_const_pathname(head, rb_id2str(tail));
195 }
196 
197 void
199 {
200  VALUE str;
201  ID pathid = classpath;
202 
203  if (under == rb_cObject) {
205  }
206  else {
207  int permanent;
208  str = rb_tmp_class_path(under, &permanent, make_temporary_path);
209  str = build_const_pathname(str, name);
210  if (!permanent) {
211  pathid = tmp_classpath;
212  }
213  }
214  rb_ivar_set(klass, pathid, str);
215 }
216 
217 void
218 rb_set_class_path(VALUE klass, VALUE under, const char *name)
219 {
221  OBJ_FREEZE(str);
223 }
224 
225 VALUE
227 {
228  rb_encoding *enc = rb_enc_get(pathname);
229  const char *pbeg, *pend, *p, *path = RSTRING_PTR(pathname);
230  ID id;
231  VALUE c = rb_cObject;
232 
233  if (!rb_enc_asciicompat(enc)) {
234  rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
235  }
236  pbeg = p = path;
237  pend = path + RSTRING_LEN(pathname);
238  if (path == pend || path[0] == '#') {
239  rb_raise(rb_eArgError, "can't retrieve anonymous class %"PRIsVALUE,
240  QUOTE(pathname));
241  }
242  while (p < pend) {
243  while (p < pend && *p != ':') p++;
244  id = rb_check_id_cstr(pbeg, p-pbeg, enc);
245  if (p < pend && p[0] == ':') {
246  if ((size_t)(pend - p) < 2 || p[1] != ':') goto undefined_class;
247  p += 2;
248  pbeg = p;
249  }
250  if (!id) {
251  undefined_class:
252  rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE,
253  rb_str_subseq(pathname, 0, p-path));
254  }
255  c = rb_const_search(c, id, TRUE, FALSE, FALSE);
256  if (c == Qundef) goto undefined_class;
257  if (!rb_namespace_p(c)) {
258  rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
259  pathname);
260  }
261  }
262  RB_GC_GUARD(pathname);
263 
264  return c;
265 }
266 
267 VALUE
268 rb_path2class(const char *path)
269 {
271 }
272 
273 VALUE
275 {
277 }
278 
279 const char *
281 {
282  int permanent;
283  VALUE path = rb_tmp_class_path(rb_class_real(klass), &permanent, make_temporary_path);
284  if (NIL_P(path)) return NULL;
285  return RSTRING_PTR(path);
286 }
287 
288 const char *
290 {
291  return rb_class2name(CLASS_OF(obj));
292 }
293 
294 struct trace_var {
295  int removed;
296  void (*func)(VALUE arg, VALUE val);
298  struct trace_var *next;
299 };
300 
302  int counter;
308  struct trace_var *trace;
309 };
310 
311 static struct rb_global_entry*
312 rb_find_global_entry(ID id)
313 {
314  struct rb_global_entry *entry;
315  VALUE data;
316 
317  if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
318  return NULL;
319  }
320  entry = (struct rb_global_entry *)data;
321  ASSUME(entry != NULL);
322  return entry;
323 }
324 
327 {
328  struct rb_global_entry *entry = rb_find_global_entry(id);
329  if (!entry) {
330  struct rb_global_variable *var;
331  entry = ALLOC(struct rb_global_entry);
332  var = ALLOC(struct rb_global_variable);
333  entry->id = id;
334  entry->var = var;
335  var->counter = 1;
336  var->data = 0;
340 
341  var->block_trace = 0;
342  var->trace = 0;
343  rb_id_table_insert(rb_global_tbl, id, (VALUE)entry);
344  }
345  return entry;
346 }
347 
348 VALUE
350 {
351  rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id));
352 
353  return Qnil;
354 }
355 
356 void
358 {
359  struct rb_global_variable *var = rb_global_entry(id)->var;
360  var->getter = rb_gvar_val_getter;
361  var->setter = rb_gvar_val_setter;
362  var->marker = rb_gvar_val_marker;
363 
364  var->data = (void*)val;
365 }
366 
367 void
369 {
370 }
371 
372 VALUE
374 {
375  return (VALUE)data;
376 }
377 
378 void
380 {
381  struct rb_global_variable *var = rb_global_entry(id)->var;
382  var->data = (void*)val;
383 }
384 
385 void
387 {
388  VALUE data = (VALUE)var;
389  if (data) rb_gc_mark_maybe(data);
390 }
391 
392 VALUE
394 {
395  if (!var) return Qnil;
396  return *var;
397 }
398 
399 void
401 {
402  *data = val;
403 }
404 
405 void
407 {
408  if (var) rb_gc_mark_maybe(*var);
409 }
410 
411 void
413 {
414  rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id));
415 }
416 
417 static enum rb_id_table_iterator_result
418 mark_global_entry(VALUE v, void *ignored)
419 {
420  struct rb_global_entry *entry = (struct rb_global_entry *)v;
421  struct trace_var *trace;
422  struct rb_global_variable *var = entry->var;
423 
424  (*var->marker)(var->data);
425  trace = var->trace;
426  while (trace) {
428  trace = trace->next;
429  }
430  return ID_TABLE_CONTINUE;
431 }
432 
433 void
435 {
436  if (rb_global_tbl)
437  rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
438 }
439 
440 static ID
441 global_id(const char *name)
442 {
443  ID id;
444 
445  if (name[0] == '$') id = rb_intern(name);
446  else {
447  size_t len = strlen(name);
448  VALUE vbuf = 0;
449  char *buf = ALLOCV_N(char, vbuf, len+1);
450  buf[0] = '$';
451  memcpy(buf+1, name, len);
452  id = rb_intern2(buf, len+1);
453  ALLOCV_END(vbuf);
454  }
455  return id;
456 }
457 
458 static ID
459 find_global_id(const char *name)
460 {
461  ID id;
462  size_t len = strlen(name);
463 
464  if (name[0] == '$') {
465  id = rb_check_id_cstr(name, len, NULL);
466  }
467  else {
468  VALUE vbuf = 0;
469  char *buf = ALLOCV_N(char, vbuf, len+1);
470  buf[0] = '$';
471  memcpy(buf+1, name, len);
472  id = rb_check_id_cstr(buf, len+1, NULL);
473  ALLOCV_END(vbuf);
474  }
475 
476  return id;
477 }
478 
479 void
481  const char *name,
482  VALUE *var,
485 {
486  volatile VALUE tmp = var ? *var : Qnil;
487  ID id = global_id(name);
488  struct rb_global_variable *gvar = rb_global_entry(id)->var;
489 
490  gvar->data = (void*)var;
493  gvar->marker = rb_gvar_var_marker;
494 
495  RB_GC_GUARD(tmp);
496 }
497 
498 void
499 rb_define_variable(const char *name, VALUE *var)
500 {
501  rb_define_hooked_variable(name, var, 0, 0);
502 }
503 
504 void
505 rb_define_readonly_variable(const char *name, const VALUE *var)
506 {
508 }
509 
510 void
512  const char *name,
515 {
519 }
520 
521 static void
522 rb_trace_eval(VALUE cmd, VALUE val)
523 {
525 }
526 
527 VALUE
529 {
530  VALUE var, cmd;
531  struct rb_global_entry *entry;
532  struct trace_var *trace;
533 
534  if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
535  cmd = rb_block_proc();
536  }
537  if (NIL_P(cmd)) {
538  return rb_f_untrace_var(argc, argv);
539  }
540  entry = rb_global_entry(rb_to_id(var));
541  trace = ALLOC(struct trace_var);
542  trace->next = entry->var->trace;
543  trace->func = rb_trace_eval;
544  trace->data = cmd;
545  trace->removed = 0;
546  entry->var->trace = trace;
547 
548  return Qnil;
549 }
550 
551 static void
552 remove_trace(struct rb_global_variable *var)
553 {
554  struct trace_var *trace = var->trace;
555  struct trace_var t;
556  struct trace_var *next;
557 
558  t.next = trace;
559  trace = &t;
560  while (trace->next) {
561  next = trace->next;
562  if (next->removed) {
563  trace->next = next->next;
564  xfree(next);
565  }
566  else {
567  trace = next;
568  }
569  }
570  var->trace = t.next;
571 }
572 
573 VALUE
575 {
576  VALUE var, cmd;
577  ID id;
578  struct rb_global_entry *entry;
579  struct trace_var *trace;
580  VALUE data;
581 
582  rb_scan_args(argc, argv, "11", &var, &cmd);
583  id = rb_check_id(&var);
584  if (!id) {
585  rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
586  }
587  if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
588  rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
589  }
590 
591  trace = (entry = (struct rb_global_entry *)data)->var->trace;
592  if (NIL_P(cmd)) {
593  VALUE ary = rb_ary_new();
594 
595  while (trace) {
596  struct trace_var *next = trace->next;
597  rb_ary_push(ary, (VALUE)trace->data);
598  trace->removed = 1;
599  trace = next;
600  }
601 
602  if (!entry->var->block_trace) remove_trace(entry->var);
603  return ary;
604  }
605  else {
606  while (trace) {
607  if (trace->data == cmd) {
608  trace->removed = 1;
609  if (!entry->var->block_trace) remove_trace(entry->var);
610  return rb_ary_new3(1, cmd);
611  }
612  trace = trace->next;
613  }
614  }
615  return Qnil;
616 }
617 
620 {
621  struct rb_global_variable *var = entry->var;
622  return (*var->getter)(entry->id, var->data);
623 }
624 
625 struct trace_data {
626  struct trace_var *trace;
628 };
629 
630 static VALUE
631 trace_ev(VALUE v)
632 {
633  struct trace_data *data = (void *)v;
634  struct trace_var *trace = data->trace;
635 
636  while (trace) {
637  (*trace->func)(trace->data, data->val);
638  trace = trace->next;
639  }
640 
641  return Qnil;
642 }
643 
644 static VALUE
645 trace_en(VALUE v)
646 {
647  struct rb_global_variable *var = (void *)v;
648  var->block_trace = 0;
649  remove_trace(var);
650  return Qnil; /* not reached */
651 }
652 
654 rb_gvar_set(struct rb_global_entry *entry, VALUE val)
655 {
656  struct trace_data trace;
657  struct rb_global_variable *var = entry->var;
658 
659  (*var->setter)(val, entry->id, var->data);
660 
661  if (var->trace && !var->block_trace) {
662  var->block_trace = 1;
663  trace.trace = var->trace;
664  trace.val = val;
665  rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
666  }
667  return val;
668 }
669 
670 VALUE
671 rb_gv_set(const char *name, VALUE val)
672 {
673  struct rb_global_entry *entry;
674 
675  entry = rb_global_entry(global_id(name));
676  return rb_gvar_set(entry, val);
677 }
678 
679 VALUE
680 rb_gv_get(const char *name)
681 {
682  struct rb_global_entry *entry;
683  ID id = find_global_id(name);
684 
685  if (!id) {
686  rb_warning("global variable `%s' not initialized", name);
687  return Qnil;
688  }
689 
690  entry = rb_global_entry(id);
691  return rb_gvar_get(entry);
692 }
693 
696 {
697  if (entry->var->getter == rb_gvar_undef_getter) return Qfalse;
698  return Qtrue;
699 }
700 
703 {
704  return entry->var->getter;
705 }
706 
709 {
710  return entry->var->setter;
711 }
712 
713 bool
714 rb_gvar_is_traced(const struct rb_global_entry *entry)
715 {
716  return !!entry->var->trace;
717 }
718 
719 static enum rb_id_table_iterator_result
720 gvar_i(ID key, VALUE val, void *a)
721 {
722  VALUE ary = (VALUE)a;
723  rb_ary_push(ary, ID2SYM(key));
724  return ID_TABLE_CONTINUE;
725 }
726 
727 VALUE
729 {
730  VALUE ary = rb_ary_new();
731  VALUE sym, backref = rb_backref_get();
732 
733  rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary);
734  if (!NIL_P(backref)) {
735  char buf[2];
736  int i, nmatch = rb_match_count(backref);
737  buf[0] = '$';
738  for (i = 1; i <= nmatch; ++i) {
739  if (!rb_match_nth_defined(i, backref)) continue;
740  if (i < 10) {
741  /* probably reused, make static ID */
742  buf[1] = (char)(i + '0');
743  sym = ID2SYM(rb_intern2(buf, 2));
744  }
745  else {
746  /* dynamic symbol */
747  sym = rb_str_intern(rb_sprintf("$%d", i));
748  }
749  rb_ary_push(ary, sym);
750  }
751  }
752  return ary;
753 }
754 
755 void
756 rb_alias_variable(ID name1, ID name2)
757 {
758  struct rb_global_entry *entry1, *entry2;
759  VALUE data1;
760 
761  entry2 = rb_global_entry(name2);
762  if (!rb_id_table_lookup(rb_global_tbl, name1, &data1)) {
763  entry1 = ALLOC(struct rb_global_entry);
764  entry1->id = name1;
765  rb_id_table_insert(rb_global_tbl, name1, (VALUE)entry1);
766  }
767  else if ((entry1 = (struct rb_global_entry *)data1)->var != entry2->var) {
768  struct rb_global_variable *var = entry1->var;
769  if (var->block_trace) {
770  rb_raise(rb_eRuntimeError, "can't alias in tracer");
771  }
772  var->counter--;
773  if (var->counter == 0) {
774  struct trace_var *trace = var->trace;
775  while (trace) {
776  struct trace_var *next = trace->next;
777  xfree(trace);
778  trace = next;
779  }
780  xfree(var);
781  }
782  }
783  else {
784  return;
785  }
786  entry2->var->counter++;
787  entry1->var = entry2->var;
788 }
789 
790 static int
791 gen_ivtbl_get(VALUE obj, struct gen_ivtbl **ivtbl)
792 {
793  st_data_t data;
794 
795  if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
796  *ivtbl = (struct gen_ivtbl *)data;
797  return 1;
798  }
799  return 0;
800 }
801 
804 {
805  return generic_iv_tbl;
806 }
807 
808 static VALUE
809 generic_ivar_delete(VALUE obj, ID id, VALUE undef)
810 {
811  struct gen_ivtbl *ivtbl;
812 
813  if (gen_ivtbl_get(obj, &ivtbl)) {
814  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
816 
817  if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
818  if (index < ivtbl->numiv) {
819  VALUE ret = ivtbl->ivptr[index];
820 
821  ivtbl->ivptr[index] = Qundef;
822  return ret == Qundef ? undef : ret;
823  }
824  }
825  }
826  return undef;
827 }
828 
829 static VALUE
830 generic_ivar_get(VALUE obj, ID id, VALUE undef)
831 {
832  struct gen_ivtbl *ivtbl;
833 
834  if (gen_ivtbl_get(obj, &ivtbl)) {
835  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
837 
838  if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
839  if (index < ivtbl->numiv) {
840  VALUE ret = ivtbl->ivptr[index];
841 
842  return ret == Qundef ? undef : ret;
843  }
844  }
845  }
846  return undef;
847 }
848 
849 static size_t
850 gen_ivtbl_bytes(size_t n)
851 {
852  return offsetof(struct gen_ivtbl, ivptr) + n * sizeof(VALUE);
853 }
854 
855 static struct gen_ivtbl *
856 gen_ivtbl_resize(struct gen_ivtbl *old, uint32_t n)
857 {
858  uint32_t len = old ? old->numiv : 0;
859  struct gen_ivtbl *ivtbl = xrealloc(old, gen_ivtbl_bytes(n));
860 
861  ivtbl->numiv = n;
862  for (; len < n; len++) {
863  ivtbl->ivptr[len] = Qundef;
864  }
865 
866  return ivtbl;
867 }
868 
869 #if 0
870 static struct gen_ivtbl *
871 gen_ivtbl_dup(const struct gen_ivtbl *orig)
872 {
873  size_t s = gen_ivtbl_bytes(orig->numiv);
874  struct gen_ivtbl *ivtbl = xmalloc(s);
875 
876  memcpy(ivtbl, orig, s);
877 
878  return ivtbl;
879 }
880 #endif
881 
882 static uint32_t
883 iv_index_tbl_newsize(struct ivar_update *ivup)
884 {
885  uint32_t index = (uint32_t)ivup->index; /* should not overflow */
886  uint32_t newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */
887 
888  if (!ivup->iv_extended &&
889  ivup->u.iv_index_tbl->num_entries < (st_index_t)newsize) {
890  newsize = (uint32_t)ivup->u.iv_index_tbl->num_entries;
891  }
892  return newsize;
893 }
894 
895 static int
896 generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
897 {
898  VALUE obj = (VALUE)*k;
899  struct ivar_update *ivup = (struct ivar_update *)u;
900  uint32_t newsize;
901  int ret = ST_CONTINUE;
902  struct gen_ivtbl *ivtbl;
903 
904  if (existing) {
905  ivtbl = (struct gen_ivtbl *)*v;
906  if (ivup->index >= ivtbl->numiv) {
907  goto resize;
908  }
909  ret = ST_STOP;
910  }
911  else {
912  FL_SET(obj, FL_EXIVAR);
913  ivtbl = 0;
914 resize:
915  newsize = iv_index_tbl_newsize(ivup);
916  ivtbl = gen_ivtbl_resize(ivtbl, newsize);
917  *v = (st_data_t)ivtbl;
918  }
919  ivup->u.ivtbl = ivtbl;
920  return ret;
921 }
922 
923 static VALUE
924 generic_ivar_defined(VALUE obj, ID id)
925 {
926  struct gen_ivtbl *ivtbl;
927  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
929 
930  if (!iv_index_tbl) return Qfalse;
931  if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) return Qfalse;
932  if (!gen_ivtbl_get(obj, &ivtbl)) return Qfalse;
933 
934  if ((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef))
935  return Qtrue;
936 
937  return Qfalse;
938 }
939 
940 static int
941 generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
942 {
943  struct gen_ivtbl *ivtbl;
944  st_data_t key = (st_data_t)id;
946  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
947 
948  if (!iv_index_tbl) return 0;
949  if (!st_lookup(iv_index_tbl, key, &index)) return 0;
950  if (!gen_ivtbl_get(obj, &ivtbl)) return 0;
951 
952  if (index < ivtbl->numiv) {
953  if (ivtbl->ivptr[index] != Qundef) {
954  *valp = ivtbl->ivptr[index];
955  ivtbl->ivptr[index] = Qundef;
956  return 1;
957  }
958  }
959  return 0;
960 }
961 
962 static void
963 gen_ivtbl_mark(const struct gen_ivtbl *ivtbl)
964 {
965  uint32_t i;
966 
967  for (i = 0; i < ivtbl->numiv; i++) {
968  rb_gc_mark(ivtbl->ivptr[i]);
969  }
970 }
971 
972 void
974 {
975  struct gen_ivtbl *ivtbl;
976 
977  if (gen_ivtbl_get(obj, &ivtbl)) {
978  gen_ivtbl_mark(ivtbl);
979  }
980 }
981 
982 void
984 {
985  st_data_t key = (st_data_t)rsrc;
986  struct gen_ivtbl *ivtbl;
987 
988  if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl))
989  st_insert(generic_iv_tbl, (st_data_t)dst, (st_data_t)ivtbl);
990 }
991 
992 void
994 {
996  struct gen_ivtbl *ivtbl;
997 
998  if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl))
999  xfree(ivtbl);
1000 
1001  if (generic_iv_tbl_compat) {
1002  st_table *tbl;
1003 
1004  if (st_delete(generic_iv_tbl_compat, &key, (st_data_t *)&tbl))
1005  st_free_table(tbl);
1006  }
1007 }
1008 
1009 RUBY_FUNC_EXPORTED size_t
1011 {
1012  struct gen_ivtbl *ivtbl;
1013 
1014  if (gen_ivtbl_get(obj, &ivtbl))
1015  return gen_ivtbl_bytes(ivtbl->numiv);
1016  return 0;
1017 }
1018 
1019 static size_t
1020 gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
1021 {
1022  uint32_t i;
1023  size_t n = 0;
1024 
1025  for (i = 0; i < ivtbl->numiv; i++) {
1026  if (ivtbl->ivptr[i] != Qundef) {
1027  n++;
1028  }
1029  }
1030 
1031  return n;
1032 }
1033 
1034 VALUE
1036 {
1037  VALUE val, *ptr;
1038  struct st_table *iv_index_tbl;
1039  uint32_t len;
1040  st_data_t index;
1041 
1042  if (SPECIAL_CONST_P(obj)) return undef;
1043  switch (BUILTIN_TYPE(obj)) {
1044  case T_OBJECT:
1045  len = ROBJECT_NUMIV(obj);
1046  ptr = ROBJECT_IVPTR(obj);
1047  iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1048  if (!iv_index_tbl) break;
1049  if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
1050  if (len <= index) break;
1051  val = ptr[index];
1052  if (val != Qundef)
1053  return val;
1054  break;
1055  case T_CLASS:
1056  case T_MODULE:
1057  if (RCLASS_IV_TBL(obj) &&
1059  return (VALUE)index;
1060  break;
1061  default:
1062  if (FL_TEST(obj, FL_EXIVAR))
1063  return generic_ivar_get(obj, id, undef);
1064  break;
1065  }
1066  return undef;
1067 }
1068 
1069 VALUE
1071 {
1072  VALUE iv = rb_ivar_lookup(obj, id, Qundef);
1073  RB_DEBUG_COUNTER_INC(ivar_get_base);
1074 
1075  if (iv == Qundef) {
1076  if (RTEST(ruby_verbose))
1077  rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id));
1078  iv = Qnil;
1079  }
1080  return iv;
1081 }
1082 
1083 VALUE
1085 {
1086  return rb_ivar_lookup(obj, id, Qnil);
1087 }
1088 
1089 static VALUE
1090 rb_ivar_delete(VALUE obj, ID id, VALUE undef)
1091 {
1092  VALUE val, *ptr;
1093  struct st_table *iv_index_tbl;
1094  uint32_t len;
1095  st_data_t index;
1096 
1098  switch (BUILTIN_TYPE(obj)) {
1099  case T_OBJECT:
1100  len = ROBJECT_NUMIV(obj);
1101  ptr = ROBJECT_IVPTR(obj);
1102  iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1103  if (!iv_index_tbl) break;
1104  if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
1105  if (len <= index) break;
1106  val = ptr[index];
1107  ptr[index] = Qundef;
1108  if (val != Qundef)
1109  return val;
1110  break;
1111  case T_CLASS:
1112  case T_MODULE:
1113  if (RCLASS_IV_TBL(obj) &&
1115  return (VALUE)index;
1116  break;
1117  default:
1118  if (FL_TEST(obj, FL_EXIVAR))
1119  return generic_ivar_delete(obj, id, undef);
1120  break;
1121  }
1122  return undef;
1123 }
1124 
1125 VALUE
1127 {
1128  return rb_ivar_delete(obj, id, Qnil);
1129 }
1130 
1131 static st_table *
1132 iv_index_tbl_make(VALUE obj)
1133 {
1135  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(klass);
1136 
1137  if (!iv_index_tbl) {
1138  iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
1139  }
1140 
1141  return iv_index_tbl;
1142 }
1143 
1144 static void
1145 iv_index_tbl_extend(struct ivar_update *ivup, ID id)
1146 {
1147  if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ivup->index)) {
1148  return;
1149  }
1150  if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) {
1151  rb_raise(rb_eArgError, "too many instance variables");
1152  }
1153  ivup->index = (st_data_t)ivup->u.iv_index_tbl->num_entries;
1154  st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, ivup->index);
1155  ivup->iv_extended = 1;
1156 }
1157 
1158 static void
1159 generic_ivar_set(VALUE obj, ID id, VALUE val)
1160 {
1161  struct ivar_update ivup;
1162 
1163  ivup.iv_extended = 0;
1164  ivup.u.iv_index_tbl = iv_index_tbl_make(obj);
1165  iv_index_tbl_extend(&ivup, id);
1166  st_update(generic_iv_tbl, (st_data_t)obj, generic_ivar_update,
1167  (st_data_t)&ivup);
1168 
1169  ivup.u.ivtbl->ivptr[ivup.index] = val;
1170 
1171  RB_OBJ_WRITTEN(obj, Qundef, val);
1172 }
1173 
1174 static VALUE *
1175 obj_ivar_heap_alloc(VALUE obj, size_t newsize)
1176 {
1177  VALUE *newptr = rb_transient_heap_alloc(obj, sizeof(VALUE) * newsize);
1178 
1179  if (newptr != NULL) {
1181  }
1182  else {
1184  newptr = ALLOC_N(VALUE, newsize);
1185  }
1186  return newptr;
1187 }
1188 
1189 static VALUE *
1190 obj_ivar_heap_realloc(VALUE obj, int32_t len, size_t newsize)
1191 {
1192  VALUE *newptr;
1193  int i;
1194 
1195  if (ROBJ_TRANSIENT_P(obj)) {
1196  const VALUE *orig_ptr = ROBJECT(obj)->as.heap.ivptr;
1197  newptr = obj_ivar_heap_alloc(obj, newsize);
1198 
1199  assert(newptr);
1200  ROBJECT(obj)->as.heap.ivptr = newptr;
1201  for (i=0; i<(int)len; i++) {
1202  newptr[i] = orig_ptr[i];
1203  }
1204  }
1205  else {
1206  REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize);
1207  newptr = ROBJECT(obj)->as.heap.ivptr;
1208  }
1209 
1210  return newptr;
1211 }
1212 
1213 #if USE_TRANSIENT_HEAP
1214 void
1216 {
1217  if (ROBJ_TRANSIENT_P(obj)) {
1219  const VALUE *old_ptr = ROBJECT_IVPTR(obj);
1220  VALUE *new_ptr;
1221 
1222  if (promote) {
1223  new_ptr = ALLOC_N(VALUE, len);
1225  }
1226  else {
1227  new_ptr = obj_ivar_heap_alloc(obj, len);
1228  }
1229  MEMCPY(new_ptr, old_ptr, VALUE, len);
1230  ROBJECT(obj)->as.heap.ivptr = new_ptr;
1231  }
1232 }
1233 #endif
1234 
1235 static VALUE
1236 obj_ivar_set(VALUE obj, ID id, VALUE val)
1237 {
1238  struct ivar_update ivup;
1239  uint32_t i, len;
1240 
1241  ivup.iv_extended = 0;
1242  ivup.u.iv_index_tbl = iv_index_tbl_make(obj);
1243  iv_index_tbl_extend(&ivup, id);
1244  len = ROBJECT_NUMIV(obj);
1245  if (len <= ivup.index) {
1246  VALUE *ptr = ROBJECT_IVPTR(obj);
1247  if (ivup.index < ROBJECT_EMBED_LEN_MAX) {
1248  RBASIC(obj)->flags |= ROBJECT_EMBED;
1249  ptr = ROBJECT(obj)->as.ary;
1250  for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) {
1251  ptr[i] = Qundef;
1252  }
1253  }
1254  else {
1255  VALUE *newptr;
1256  uint32_t newsize = iv_index_tbl_newsize(&ivup);
1257 
1258  if (RBASIC(obj)->flags & ROBJECT_EMBED) {
1259  newptr = obj_ivar_heap_alloc(obj, newsize);
1260  MEMCPY(newptr, ptr, VALUE, len);
1261  RBASIC(obj)->flags &= ~ROBJECT_EMBED;
1262  ROBJECT(obj)->as.heap.ivptr = newptr;
1263  }
1264  else {
1265  newptr = obj_ivar_heap_realloc(obj, len, newsize);
1266  }
1267  for (; len < newsize; len++) {
1268  newptr[len] = Qundef;
1269  }
1270  ROBJECT(obj)->as.heap.numiv = newsize;
1271  ROBJECT(obj)->as.heap.iv_index_tbl = ivup.u.iv_index_tbl;
1272  }
1273  }
1274  RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
1275 
1276  return val;
1277 }
1278 
1279 static void
1280 ivar_set(VALUE obj, ID id, VALUE val)
1281 {
1282  RB_DEBUG_COUNTER_INC(ivar_set_base);
1283 
1284  switch (BUILTIN_TYPE(obj)) {
1285  case T_OBJECT:
1286  obj_ivar_set(obj, id, val);
1287  break;
1288  case T_CLASS:
1289  case T_MODULE:
1291  rb_class_ivar_set(obj, id, val);
1292  break;
1293  default:
1294  generic_ivar_set(obj, id, val);
1295  break;
1296  }
1297 }
1298 
1299 VALUE
1301 {
1303  ivar_set(obj, id, val);
1304  return val;
1305 }
1306 
1307 void
1309 {
1310  // should be internal instance variable name (no @ prefix)
1312 
1313  ivar_set(obj, id, val);
1314 }
1315 
1316 VALUE
1318 {
1319  VALUE val;
1320  struct st_table *iv_index_tbl;
1321  st_data_t index;
1322 
1323  if (SPECIAL_CONST_P(obj)) return Qfalse;
1324  switch (BUILTIN_TYPE(obj)) {
1325  case T_OBJECT:
1326  iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1327  if (!iv_index_tbl) break;
1328  if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
1329  if (ROBJECT_NUMIV(obj) <= index) break;
1330  val = ROBJECT_IVPTR(obj)[index];
1331  if (val != Qundef)
1332  return Qtrue;
1333  break;
1334  case T_CLASS:
1335  case T_MODULE:
1337  return Qtrue;
1338  break;
1339  default:
1340  if (FL_TEST(obj, FL_EXIVAR))
1341  return generic_ivar_defined(obj, id);
1342  break;
1343  }
1344  return Qfalse;
1345 }
1346 
1348 
1353 };
1354 
1355 static int
1356 obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg)
1357 {
1358  struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg;
1359  if (index < ROBJECT_NUMIV(data->obj)) {
1360  VALUE val = ROBJECT_IVPTR(data->obj)[index];
1361  if (val != Qundef) {
1362  return (data->func)((ID)key, val, data->arg);
1363  }
1364  }
1365  return ST_CONTINUE;
1366 }
1367 
1368 static void
1370 {
1371  st_table *tbl;
1372  struct obj_ivar_tag data;
1373 
1374  tbl = ROBJECT_IV_INDEX_TBL(obj);
1375  if (!tbl)
1376  return;
1377 
1378  data.obj = obj;
1379  data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
1380  data.arg = arg;
1381 
1382  st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
1383 }
1384 
1386  struct gen_ivtbl *ivtbl;
1389 };
1390 
1391 static int
1392 gen_ivar_each_i(st_data_t key, st_data_t index, st_data_t data)
1393 {
1394  struct gen_ivar_tag *arg = (struct gen_ivar_tag *)data;
1395 
1396  if (index < arg->ivtbl->numiv) {
1397  VALUE val = arg->ivtbl->ivptr[index];
1398  if (val != Qundef) {
1399  return (arg->func)((ID)key, val, arg->arg);
1400  }
1401  }
1402  return ST_CONTINUE;
1403 }
1404 
1405 static void
1407 {
1408  struct gen_ivar_tag data;
1409  st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
1410 
1411  if (!iv_index_tbl) return;
1412  if (!gen_ivtbl_get(obj, &data.ivtbl)) return;
1413 
1414  data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
1415  data.arg = arg;
1416 
1417  st_foreach_safe(iv_index_tbl, gen_ivar_each_i, (st_data_t)&data);
1418 }
1419 
1420 struct givar_copy {
1423  struct gen_ivtbl *ivtbl;
1424 };
1425 
1426 static int
1427 gen_ivar_copy(ID id, VALUE val, st_data_t arg)
1428 {
1429  struct givar_copy *c = (struct givar_copy *)arg;
1430  struct ivar_update ivup;
1431 
1432  ivup.iv_extended = 0;
1433  ivup.u.iv_index_tbl = c->iv_index_tbl;
1434  iv_index_tbl_extend(&ivup, id);
1435  if (ivup.index >= c->ivtbl->numiv) {
1436  uint32_t newsize = iv_index_tbl_newsize(&ivup);
1437  c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize);
1438  }
1439  c->ivtbl->ivptr[ivup.index] = val;
1440 
1441  RB_OBJ_WRITTEN(c->obj, Qundef, val);
1442 
1443  return ST_CONTINUE;
1444 }
1445 
1446 void
1448 {
1449  struct gen_ivtbl *ivtbl;
1450 
1451  rb_check_frozen(clone);
1452 
1453  if (!FL_TEST(obj, FL_EXIVAR)) {
1454  clear:
1455  if (FL_TEST(clone, FL_EXIVAR)) {
1456  rb_free_generic_ivar(clone);
1457  FL_UNSET(clone, FL_EXIVAR);
1458  }
1459  return;
1460  }
1461  if (gen_ivtbl_get(obj, &ivtbl)) {
1462  struct givar_copy c;
1463  uint32_t i;
1464 
1465  if (gen_ivtbl_count(ivtbl) == 0)
1466  goto clear;
1467 
1468  if (gen_ivtbl_get(clone, &c.ivtbl)) {
1469  for (i = 0; i < c.ivtbl->numiv; i++)
1470  c.ivtbl->ivptr[i] = Qundef;
1471  }
1472  else {
1473  c.ivtbl = gen_ivtbl_resize(0, ivtbl->numiv);
1474  FL_SET(clone, FL_EXIVAR);
1475  }
1476 
1477  c.iv_index_tbl = iv_index_tbl_make(clone);
1478  c.obj = clone;
1479  gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c);
1480  /*
1481  * c.ivtbl may change in gen_ivar_copy due to realloc,
1482  * no need to free
1483  */
1484  st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)c.ivtbl);
1485  }
1486 }
1487 
1488 void
1490 {
1491  if (SPECIAL_CONST_P(obj)) return;
1492  switch (BUILTIN_TYPE(obj)) {
1493  case T_OBJECT:
1494  obj_ivar_each(obj, func, arg);
1495  break;
1496  case T_CLASS:
1497  case T_MODULE:
1498  if (RCLASS_IV_TBL(obj)) {
1500  }
1501  break;
1502  default:
1503  if (FL_TEST(obj, FL_EXIVAR)) {
1504  gen_ivar_each(obj, func, arg);
1505  }
1506  break;
1507  }
1508 }
1509 
1510 st_index_t
1512 {
1513  st_table *tbl;
1514 
1515  if (SPECIAL_CONST_P(obj)) return 0;
1516 
1517  switch (BUILTIN_TYPE(obj)) {
1518  case T_OBJECT:
1519  if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) {
1520  st_index_t i, count, num = ROBJECT_NUMIV(obj);
1521  const VALUE *const ivptr = ROBJECT_IVPTR(obj);
1522  for (i = count = 0; i < num; ++i) {
1523  if (ivptr[i] != Qundef) {
1524  count++;
1525  }
1526  }
1527  return count;
1528  }
1529  break;
1530  case T_CLASS:
1531  case T_MODULE:
1532  if ((tbl = RCLASS_IV_TBL(obj)) != 0) {
1533  return tbl->num_entries;
1534  }
1535  break;
1536  default:
1537  if (FL_TEST(obj, FL_EXIVAR)) {
1538  struct gen_ivtbl *ivtbl;
1539 
1540  if (gen_ivtbl_get(obj, &ivtbl)) {
1541  return gen_ivtbl_count(ivtbl);
1542  }
1543  }
1544  break;
1545  }
1546  return 0;
1547 }
1548 
1549 static int
1550 ivar_i(st_data_t k, st_data_t v, st_data_t a)
1551 {
1552  ID key = (ID)k;
1553  VALUE ary = (VALUE)a;
1554 
1555  if (rb_is_instance_id(key)) {
1556  rb_ary_push(ary, ID2SYM(key));
1557  }
1558  return ST_CONTINUE;
1559 }
1560 
1561 /*
1562  * call-seq:
1563  * obj.instance_variables -> array
1564  *
1565  * Returns an array of instance variable names for the receiver. Note
1566  * that simply defining an accessor does not create the corresponding
1567  * instance variable.
1568  *
1569  * class Fred
1570  * attr_accessor :a1
1571  * def initialize
1572  * @iv = 3
1573  * end
1574  * end
1575  * Fred.new.instance_variables #=> [:@iv]
1576  */
1577 
1578 VALUE
1580 {
1581  VALUE ary;
1582 
1583  ary = rb_ary_new();
1584  rb_ivar_foreach(obj, ivar_i, ary);
1585  return ary;
1586 }
1587 
1588 #define rb_is_constant_id rb_is_const_id
1589 #define rb_is_constant_name rb_is_const_name
1590 #define id_for_var(obj, name, part, type) \
1591  id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name")
1592 #define id_for_var_message(obj, name, type, message) \
1593  check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
1594 static ID
1595 check_id_type(VALUE obj, VALUE *pname,
1596  int (*valid_id_p)(ID), int (*valid_name_p)(VALUE),
1597  const char *message, size_t message_len)
1598 {
1599  ID id = rb_check_id(pname);
1600  VALUE name = *pname;
1601 
1602  if (id ? !valid_id_p(id) : !valid_name_p(name)) {
1603  rb_name_err_raise_str(rb_fstring_new(message, message_len),
1604  obj, name);
1605  }
1606  return id;
1607 }
1608 
1609 /*
1610  * call-seq:
1611  * obj.remove_instance_variable(symbol) -> obj
1612  * obj.remove_instance_variable(string) -> obj
1613  *
1614  * Removes the named instance variable from <i>obj</i>, returning that
1615  * variable's value.
1616  * String arguments are converted to symbols.
1617  *
1618  * class Dummy
1619  * attr_reader :var
1620  * def initialize
1621  * @var = 99
1622  * end
1623  * def remove
1624  * remove_instance_variable(:@var)
1625  * end
1626  * end
1627  * d = Dummy.new
1628  * d.var #=> 99
1629  * d.remove #=> 99
1630  * d.var #=> nil
1631  */
1632 
1633 VALUE
1635 {
1636  VALUE val = Qnil;
1637  const ID id = id_for_var(obj, name, an, instance);
1638  st_data_t n, v;
1639  struct st_table *iv_index_tbl;
1640  st_data_t index;
1641 
1643  if (!id) {
1644  goto not_defined;
1645  }
1646 
1647  switch (BUILTIN_TYPE(obj)) {
1648  case T_OBJECT:
1649  iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1650  if (!iv_index_tbl) break;
1651  if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
1652  if (ROBJECT_NUMIV(obj) <= index) break;
1653  val = ROBJECT_IVPTR(obj)[index];
1654  if (val != Qundef) {
1656  return val;
1657  }
1658  break;
1659  case T_CLASS:
1660  case T_MODULE:
1661  n = id;
1662  if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
1663  return (VALUE)v;
1664  }
1665  break;
1666  default:
1667  if (FL_TEST(obj, FL_EXIVAR)) {
1668  if (generic_ivar_remove(obj, id, &val)) {
1669  return val;
1670  }
1671  }
1672  break;
1673  }
1674 
1675  not_defined:
1676  rb_name_err_raise("instance variable %1$s not defined",
1677  obj, name);
1679 }
1680 
1681 NORETURN(static void uninitialized_constant(VALUE, VALUE));
1682 static void
1683 uninitialized_constant(VALUE klass, VALUE name)
1684 {
1685  if (klass && rb_class_real(klass) != rb_cObject)
1686  rb_name_err_raise("uninitialized constant %2$s::%1$s",
1687  klass, name);
1688  else
1689  rb_name_err_raise("uninitialized constant %1$s",
1690  klass, name);
1691 }
1692 
1693 VALUE
1695 {
1696  VALUE value = rb_funcallv(klass, idConst_missing, 1, &name);
1698  return value;
1699 }
1700 
1701 
1702 /*
1703  * call-seq:
1704  * mod.const_missing(sym) -> obj
1705  *
1706  * Invoked when a reference is made to an undefined constant in
1707  * <i>mod</i>. It is passed a symbol for the undefined constant, and
1708  * returns a value to be used for that constant. The
1709  * following code is an example of the same:
1710  *
1711  * def Foo.const_missing(name)
1712  * name # return the constant name as Symbol
1713  * end
1714  *
1715  * Foo::UNDEFINED_CONST #=> :UNDEFINED_CONST: symbol returned
1716  *
1717  * In the next example when a reference is made to an undefined constant,
1718  * it attempts to load a file whose name is the lowercase version of the
1719  * constant (thus class <code>Fred</code> is assumed to be in file
1720  * <code>fred.rb</code>). If found, it returns the loaded class. It
1721  * therefore implements an autoload feature similar to Kernel#autoload and
1722  * Module#autoload.
1723  *
1724  * def Object.const_missing(name)
1725  * @looked_for ||= {}
1726  * str_name = name.to_s
1727  * raise "Class not found: #{name}" if @looked_for[str_name]
1728  * @looked_for[str_name] = 1
1729  * file = str_name.downcase
1730  * require file
1731  * klass = const_get(name)
1732  * return klass if klass
1733  * raise "Class not found: #{name}"
1734  * end
1735  *
1736  */
1737 
1738 VALUE
1740 {
1741  VALUE ref = GET_EC()->private_const_reference;
1743  if (ref) {
1744  rb_name_err_raise("private constant %2$s::%1$s referenced",
1745  ref, name);
1746  }
1747  uninitialized_constant(klass, name);
1748 
1750 }
1751 
1752 static void
1753 autoload_mark(void *ptr)
1754 {
1756 }
1757 
1758 static void
1759 autoload_free(void *ptr)
1760 {
1762 }
1763 
1764 static size_t
1765 autoload_memsize(const void *ptr)
1766 {
1767  const st_table *tbl = ptr;
1768  return st_memsize(tbl);
1769 }
1770 
1771 static void
1772 autoload_compact(void *ptr)
1773 {
1775 }
1776 
1777 static const rb_data_type_t autoload_data_type = {
1778  "autoload",
1779  {autoload_mark, autoload_free, autoload_memsize, autoload_compact,},
1781 };
1782 
1783 #define check_autoload_table(av) \
1784  (struct st_table *)rb_check_typeddata((av), &autoload_data_type)
1785 
1786 static VALUE
1787 autoload_data(VALUE mod, ID id)
1788 {
1789  struct st_table *tbl;
1790  st_data_t val;
1791 
1792  if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
1793  !(tbl = check_autoload_table((VALUE)val)) ||
1794  !st_lookup(tbl, (st_data_t)id, &val)) {
1795  return 0;
1796  }
1797  return (VALUE)val;
1798 }
1799 
1801  struct list_node cnode; /* <=> autoload_data_i.constants */
1803  VALUE ad; /* autoload_data_i */
1808  int line;
1809 };
1810 
1811 /* always on stack, no need to mark */
1816  struct list_node waitq;
1817 };
1818 
1821  struct autoload_state *state; /* points to on-stack struct */
1823  struct list_head constants; /* <=> autoload_const.cnode */
1824 };
1825 
1826 static void
1827 autoload_i_compact(void *ptr)
1828 {
1829  struct autoload_data_i *p = ptr;
1830  p->feature = rb_gc_location(p->feature);
1831 }
1832 
1833 static void
1834 autoload_i_mark(void *ptr)
1835 {
1836  struct autoload_data_i *p = ptr;
1837 
1839 
1840  /* allow GC to free us if no modules refer to this via autoload_const.ad */
1841  if (list_empty(&p->constants)) {
1842  rb_hash_delete(autoload_featuremap, p->feature);
1843  }
1844 }
1845 
1846 static void
1847 autoload_i_free(void *ptr)
1848 {
1849  struct autoload_data_i *p = ptr;
1850 
1851  /* we may leak some memory at VM shutdown time, no big deal */
1852  if (list_empty(&p->constants)) {
1853  xfree(p);
1854  }
1855 }
1856 
1857 static size_t
1858 autoload_i_memsize(const void *ptr)
1859 {
1860  return sizeof(struct autoload_data_i);
1861 }
1862 
1863 static const rb_data_type_t autoload_data_i_type = {
1864  "autoload_i",
1865  {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact},
1867 };
1868 
1869 static void
1870 autoload_c_compact(void *ptr)
1871 {
1872  struct autoload_const *ac = ptr;
1873 
1874  ac->mod = rb_gc_location(ac->mod);
1875  ac->ad = rb_gc_location(ac->ad);
1876  ac->value = rb_gc_location(ac->value);
1877  ac->file = rb_gc_location(ac->file);
1878 }
1879 
1880 static void
1881 autoload_c_mark(void *ptr)
1882 {
1883  struct autoload_const *ac = ptr;
1884 
1885  rb_gc_mark_movable(ac->mod);
1886  rb_gc_mark_movable(ac->ad);
1888  rb_gc_mark_movable(ac->file);
1889 }
1890 
1891 static void
1892 autoload_c_free(void *ptr)
1893 {
1894  struct autoload_const *ac = ptr;
1895  list_del(&ac->cnode);
1896  xfree(ac);
1897 }
1898 
1899 static size_t
1900 autoload_c_memsize(const void *ptr)
1901 {
1902  return sizeof(struct autoload_const);
1903 }
1904 
1905 static const rb_data_type_t autoload_const_type = {
1906  "autoload_const",
1907  {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
1909 };
1910 
1911 static struct autoload_data_i *
1912 get_autoload_data(VALUE acv, struct autoload_const **acp)
1913 {
1914  struct autoload_const *ac = rb_check_typeddata(acv, &autoload_const_type);
1915  struct autoload_data_i *ele;
1916 
1917  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
1918  /* do not reach across stack for ->state after forking: */
1919  if (ele && ele->state && ele->fork_gen != GET_VM()->fork_gen) {
1920  ele->state = 0;
1921  ele->fork_gen = 0;
1922  }
1923  if (acp) *acp = ac;
1924  return ele;
1925 }
1926 
1927 RUBY_FUNC_EXPORTED void
1928 rb_autoload(VALUE mod, ID id, const char *file)
1929 {
1930  if (!file || !*file) {
1931  rb_raise(rb_eArgError, "empty file name");
1932  }
1933  rb_autoload_str(mod, id, rb_fstring_cstr(file));
1934 }
1935 
1936 void
1938 {
1939  st_data_t av;
1940  VALUE ad;
1941  struct st_table *tbl;
1942  struct autoload_data_i *ele;
1943  rb_const_entry_t *ce;
1944 
1945  if (!rb_is_const_id(id)) {
1946  rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"",
1947  QUOTE_ID(id));
1948  }
1949 
1950  Check_Type(file, T_STRING);
1951  if (!RSTRING_LEN(file)) {
1952  rb_raise(rb_eArgError, "empty file name");
1953  }
1954 
1955  ce = rb_const_lookup(mod, id);
1956  if (ce && ce->value != Qundef) {
1957  return;
1958  }
1959 
1960  rb_const_set(mod, id, Qundef);
1961  tbl = RCLASS_IV_TBL(mod);
1962  if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
1963  tbl = check_autoload_table((VALUE)av);
1964  }
1965  else {
1966  if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
1967  av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
1968  st_add_direct(tbl, (st_data_t)autoload, av);
1969  RB_OBJ_WRITTEN(mod, Qnil, av);
1970  DATA_PTR(av) = tbl = st_init_numtable();
1971  }
1972 
1973  file = rb_fstring(file);
1974  if (!autoload_featuremap) {
1975  autoload_featuremap = rb_ident_hash_new();
1976  rb_obj_hide(autoload_featuremap);
1977  rb_gc_register_mark_object(autoload_featuremap);
1978  }
1979  ad = rb_hash_aref(autoload_featuremap, file);
1980  if (NIL_P(ad)) {
1981  ad = TypedData_Make_Struct(0, struct autoload_data_i,
1982  &autoload_data_i_type, ele);
1983  ele->feature = file;
1984  ele->state = 0;
1985  list_head_init(&ele->constants);
1986  rb_hash_aset(autoload_featuremap, file, ad);
1987  }
1988  else {
1989  ele = rb_check_typeddata(ad, &autoload_data_i_type);
1990  }
1991  {
1992  VALUE acv;
1993  struct autoload_const *ac;
1994  acv = TypedData_Make_Struct(0, struct autoload_const,
1995  &autoload_const_type, ac);
1996  ac->mod = mod;
1997  ac->id = id;
1998  ac->value = Qundef;
1999  ac->flag = CONST_PUBLIC;
2000  ac->ad = ad;
2001  list_add_tail(&ele->constants, &ac->cnode);
2002  st_insert(tbl, (st_data_t)id, (st_data_t)acv);
2003  }
2004 }
2005 
2006 static void
2007 autoload_delete(VALUE mod, ID id)
2008 {
2009  st_data_t val, load = 0, n = id;
2010 
2011  if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
2012  struct st_table *tbl = check_autoload_table((VALUE)val);
2013  struct autoload_data_i *ele;
2014  struct autoload_const *ac;
2015 
2016  st_delete(tbl, &n, &load);
2017  ele = get_autoload_data((VALUE)load, &ac);
2018  VM_ASSERT(ele);
2019  if (ele) {
2020  VM_ASSERT(!list_empty(&ele->constants));
2021  }
2022 
2023  /*
2024  * we must delete here to avoid "already initialized" warnings
2025  * with parallel autoload. Using list_del_init here so list_del
2026  * works in autoload_c_free
2027  */
2028  list_del_init(&ac->cnode);
2029 
2030  if (tbl->num_entries == 0) {
2031  n = autoload;
2032  st_delete(RCLASS_IV_TBL(mod), &n, &val);
2033  }
2034  }
2035 }
2036 
2037 static VALUE
2038 check_autoload_required(VALUE mod, ID id, const char **loadingpath)
2039 {
2040  VALUE file;
2041  VALUE load = autoload_data(mod, id);
2042  struct autoload_data_i *ele;
2043  const char *loading;
2044 
2045  if (!load || !(ele = get_autoload_data(load, 0))) {
2046  return 0;
2047  }
2048  file = ele->feature;
2049  Check_Type(file, T_STRING);
2050  if (!RSTRING_LEN(file) || !*RSTRING_PTR(file)) {
2051  rb_raise(rb_eArgError, "empty file name");
2052  }
2053 
2054  /*
2055  * if somebody else is autoloading, we MUST wait for them, since
2056  * rb_provide_feature can provide a feature before autoload_const_set
2057  * completes. We must wait until autoload_const_set finishes in
2058  * the other thread.
2059  */
2060  if (ele->state && ele->state->thread != rb_thread_current()) {
2061  return load;
2062  }
2063 
2064  loading = RSTRING_PTR(file);
2065  if (!rb_feature_provided(loading, &loading)) {
2066  return load;
2067  }
2068  if (loadingpath && loading) {
2069  *loadingpath = loading;
2070  return load;
2071  }
2072  return 0;
2073 }
2074 
2075 static struct autoload_const *autoloading_const_entry(VALUE mod, ID id);
2076 
2079 {
2080  struct autoload_const *ac = autoloading_const_entry(mod, id);
2081  if (!ac) return FALSE;
2082 
2083  if (value) {
2084  *value = ac->value;
2085  }
2086  if (flag) {
2087  *flag = ac->flag;
2088  }
2089  return TRUE;
2090 }
2091 
2092 struct autoload_const *
2093 autoloading_const_entry(VALUE mod, ID id)
2094 {
2095  VALUE load = autoload_data(mod, id);
2096  struct autoload_data_i *ele;
2097  struct autoload_const *ac;
2098 
2099  if (!load || !(ele = get_autoload_data(load, &ac))) {
2100  return 0;
2101  }
2102 
2103  if (ele->state && ele->state->thread == rb_thread_current()) {
2104  if (ac->value != Qundef) {
2105  return ac;
2106  }
2107  }
2108  return 0;
2109 }
2110 
2111 static int
2112 autoload_defined_p(VALUE mod, ID id)
2113 {
2115 
2116  if (!ce || ce->value != Qundef) {
2117  return 0;
2118  }
2119  return !rb_autoloading_value(mod, id, NULL, NULL);
2120 }
2121 
2122 static void const_tbl_update(struct autoload_const *);
2123 
2124 static VALUE
2125 autoload_const_set(VALUE arg)
2126 {
2127  struct autoload_const *ac = (struct autoload_const *)arg;
2128  VALUE klass = ac->mod;
2129  ID id = ac->id;
2130  check_before_mod_set(klass, id, ac->value, "constant");
2131  const_tbl_update(ac);
2132  return 0; /* ignored */
2133 }
2134 
2135 static VALUE
2136 autoload_require(VALUE arg)
2137 {
2138  struct autoload_state *state = (struct autoload_state *)arg;
2139  struct autoload_const *ac = state->ac;
2140  struct autoload_data_i *ele;
2141 
2142  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2143  /* this may release GVL and switch threads: */
2144  state->result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1,
2145  ele->feature);
2146 
2147  return state->result;
2148 }
2149 
2150 static VALUE
2151 autoload_reset(VALUE arg)
2152 {
2153  struct autoload_state *state = (struct autoload_state *)arg;
2154  int need_wakeups = 0;
2155  struct autoload_const *ac = state->ac;
2156  struct autoload_data_i *ele;
2157 
2158  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2159  if (ele->state == state) {
2160  need_wakeups = 1;
2161  ele->state = 0;
2162  ele->fork_gen = 0;
2163  }
2164 
2165  /* At the last, move a value defined in autoload to constant table */
2166  if (RTEST(state->result)) {
2167  struct autoload_const *next;
2168 
2169  list_for_each_safe(&ele->constants, ac, next, cnode) {
2170  if (ac->value != Qundef) {
2171  autoload_const_set((VALUE)ac);
2172  }
2173  }
2174  }
2175 
2176  /* wakeup any waiters we had */
2177  if (need_wakeups) {
2178  struct autoload_state *cur = 0, *nxt;
2179 
2180  list_for_each_safe((struct list_head *)&state->waitq, cur, nxt, waitq) {
2181  VALUE th = cur->thread;
2182 
2183  cur->thread = Qfalse;
2184  list_del_init(&cur->waitq); /* idempotent */
2185 
2186  /*
2187  * cur is stored on the stack of cur->waiting_th,
2188  * do not touch cur after waking up waiting_th
2189  */
2191  }
2192  }
2193 
2194  return 0; /* ignored */
2195 }
2196 
2197 static VALUE
2198 autoload_sleep(VALUE arg)
2199 {
2200  struct autoload_state *state = (struct autoload_state *)arg;
2201 
2202  /*
2203  * autoload_reset in other thread will resume us and remove us
2204  * from the waitq list
2205  */
2206  do {
2208  } while (state->thread != Qfalse);
2209 
2210  return Qfalse;
2211 }
2212 
2213 static VALUE
2214 autoload_sleep_done(VALUE arg)
2215 {
2216  struct autoload_state *state = (struct autoload_state *)arg;
2217 
2218  if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) {
2219  list_del(&state->waitq); /* idempotent after list_del_init */
2220  }
2221 
2222  return Qfalse;
2223 }
2224 
2225 VALUE
2227 {
2228  VALUE load, result;
2229  const char *loading = 0, *src;
2230  struct autoload_data_i *ele;
2231  struct autoload_const *ac;
2232  struct autoload_state state;
2233  int flag = -1;
2234  rb_const_entry_t *ce;
2235 
2236  if (!autoload_defined_p(mod, id)) return Qfalse;
2237  load = check_autoload_required(mod, id, &loading);
2238  if (!load) return Qfalse;
2239  src = rb_sourcefile();
2240  if (src && loading && strcmp(src, loading) == 0) return Qfalse;
2241 
2242  if ((ce = rb_const_lookup(mod, id))) {
2243  flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2244  }
2245 
2246  /* set ele->state for a marker of autoloading thread */
2247  if (!(ele = get_autoload_data(load, &ac))) {
2248  return Qfalse;
2249  }
2250  state.ac = ac;
2251  state.thread = rb_thread_current();
2252  if (!ele->state) {
2253  ele->state = &state;
2254  ele->fork_gen = GET_VM()->fork_gen;
2255 
2256  /*
2257  * autoload_reset will wake up any threads added to this
2258  * iff the GVL is released during autoload_require
2259  */
2260  list_head_init((struct list_head *)&state.waitq);
2261  }
2262  else if (state.thread == ele->state->thread) {
2263  return Qfalse;
2264  }
2265  else {
2266  list_add_tail((struct list_head *)&ele->state->waitq, &state.waitq);
2267 
2268  rb_ensure(autoload_sleep, (VALUE)&state,
2269  autoload_sleep_done, (VALUE)&state);
2270  }
2271 
2272  /* autoload_data_i can be deleted by another thread while require */
2273  state.result = Qfalse;
2274  result = rb_ensure(autoload_require, (VALUE)&state,
2275  autoload_reset, (VALUE)&state);
2276 
2277  if (flag > 0 && (ce = rb_const_lookup(mod, id))) {
2278  ce->flag |= flag;
2279  }
2280  RB_GC_GUARD(load);
2281  return result;
2282 }
2283 
2284 VALUE
2286 {
2287  return rb_autoload_at_p(mod, id, TRUE);
2288 }
2289 
2290 VALUE
2292 {
2293  VALUE load;
2294  struct autoload_data_i *ele;
2295 
2296  while (!autoload_defined_p(mod, id)) {
2297  if (!recur) return Qnil;
2298  mod = RCLASS_SUPER(mod);
2299  if (!mod) return Qnil;
2300  }
2301  load = check_autoload_required(mod, id, 0);
2302  if (!load) return Qnil;
2303  return (ele = get_autoload_data(load, 0)) ? ele->feature : Qnil;
2304 }
2305 
2306 MJIT_FUNC_EXPORTED void
2308 {
2309  if (RB_CONST_DEPRECATED_P(ce) &&
2311  if (klass == rb_cObject) {
2312  rb_warn("constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
2313  }
2314  else {
2315  rb_warn("constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
2316  rb_class_name(klass), QUOTE_ID(id));
2317  }
2318  }
2319 }
2320 
2321 static VALUE
2322 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2323 {
2324  VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
2325  if (c != Qundef) return c;
2326  return rb_const_missing(klass, ID2SYM(id));
2327 }
2328 
2329 static VALUE
2330 rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2331 {
2332  VALUE value, tmp;
2333 
2334  tmp = klass;
2335  while (RTEST(tmp)) {
2336  VALUE am = 0;
2337  rb_const_entry_t *ce;
2338 
2339  while ((ce = rb_const_lookup(tmp, id))) {
2340  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2341  if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass;
2342  GET_EC()->private_const_reference = tmp;
2343  return Qundef;
2344  }
2345  rb_const_warn_if_deprecated(ce, tmp, id);
2346  value = ce->value;
2347  if (value == Qundef) {
2348  struct autoload_const *ac;
2349  if (am == tmp) break;
2350  am = tmp;
2351  ac = autoloading_const_entry(tmp, id);
2352  if (ac) return ac->value;
2353  rb_autoload_load(tmp, id);
2354  continue;
2355  }
2356  if (exclude && tmp == rb_cObject) {
2357  goto not_found;
2358  }
2359  return value;
2360  }
2361  if (!recurse) break;
2362  tmp = RCLASS_SUPER(tmp);
2363  }
2364 
2365  not_found:
2366  GET_EC()->private_const_reference = 0;
2367  return Qundef;
2368 }
2369 
2370 static VALUE
2371 rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
2372 {
2373  VALUE value;
2374 
2375  if (klass == rb_cObject) exclude = FALSE;
2376  value = rb_const_search_from(klass, id, exclude, recurse, visibility);
2377  if (value != Qundef) return value;
2378  if (exclude) return value;
2379  if (BUILTIN_TYPE(klass) != T_MODULE) return value;
2380  /* search global const too, if klass is a module */
2381  return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
2382 }
2383 
2384 VALUE
2386 {
2387  return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
2388 }
2389 
2390 VALUE
2392 {
2393  return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
2394 }
2395 
2396 VALUE
2398 {
2399  return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
2400 }
2401 
2404 {
2405  return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
2406 }
2407 
2410 {
2411  return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
2412 }
2413 
2414 NORETURN(static void undefined_constant(VALUE mod, VALUE name));
2415 static void
2416 undefined_constant(VALUE mod, VALUE name)
2417 {
2418  rb_name_err_raise("constant %2$s::%1$s not defined",
2419  mod, name);
2420 }
2421 
2422 static VALUE
2423 rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2424 {
2425  while (RTEST(klass)) {
2426  rb_const_entry_t *ce;
2427 
2428  while ((ce = rb_const_lookup(klass, id))) {
2429  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2430  return Qnil;
2431  }
2432  if (exclude && klass == rb_cObject) {
2433  goto not_found;
2434  }
2435  if (NIL_P(ce->file)) return rb_ary_new();
2436  return rb_assoc_new(ce->file, INT2NUM(ce->line));
2437  }
2438  if (!recurse) break;
2440  }
2441 
2442  not_found:
2443  return Qnil;
2444 }
2445 
2446 static VALUE
2447 rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility)
2448 {
2449  VALUE loc;
2450 
2451  if (klass == rb_cObject) exclude = FALSE;
2452  loc = rb_const_location_from(klass, id, exclude, recurse, visibility);
2453  if (!NIL_P(loc)) return loc;
2454  if (exclude) return loc;
2455  if (BUILTIN_TYPE(klass) != T_MODULE) return loc;
2456  /* search global const too, if klass is a module */
2457  return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility);
2458 }
2459 
2460 VALUE
2462 {
2463  return rb_const_location(klass, id, FALSE, TRUE, FALSE);
2464 }
2465 
2468 {
2469  return rb_const_location(klass, id, TRUE, FALSE, FALSE);
2470 }
2471 
2472 /*
2473  * call-seq:
2474  * remove_const(sym) -> obj
2475  *
2476  * Removes the definition of the given constant, returning that
2477  * constant's previous value. If that constant referred to
2478  * a module, this will not change that module's name and can lead
2479  * to confusion.
2480  */
2481 
2482 VALUE
2484 {
2485  const ID id = id_for_var(mod, name, a, constant);
2486 
2487  if (!id) {
2488  undefined_constant(mod, name);
2489  }
2490  return rb_const_remove(mod, id);
2491 }
2492 
2493 VALUE
2495 {
2496  VALUE val;
2497  rb_const_entry_t *ce;
2498 
2500  ce = rb_const_lookup(mod, id);
2501  if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2502  if (rb_const_defined_at(mod, id)) {
2503  rb_name_err_raise("cannot remove %2$s::%1$s",
2504  mod, ID2SYM(id));
2505  }
2506  undefined_constant(mod, ID2SYM(id));
2507  }
2508 
2510 
2511  val = ce->value;
2512  if (val == Qundef) {
2513  autoload_delete(mod, id);
2514  val = Qnil;
2515  }
2516  xfree(ce);
2517  return val;
2518 }
2519 
2520 static int
2521 cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
2522 {
2523  if (existing) return ST_STOP;
2524  *v = a;
2525  return ST_CONTINUE;
2526 }
2527 
2528 static enum rb_id_table_iterator_result
2529 sv_i(ID key, VALUE v, void *a)
2530 {
2532  st_table *tbl = a;
2533 
2534  if (rb_is_const_id(key)) {
2535  st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2536  }
2537  return ID_TABLE_CONTINUE;
2538 }
2539 
2540 static enum rb_id_table_iterator_result
2541 rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
2542 {
2543  if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
2544  rb_ary_push((VALUE)ary, ID2SYM(const_name));
2545  }
2546  return ID_TABLE_CONTINUE;
2547 }
2548 
2549 static VALUE
2550 rb_local_constants(VALUE mod)
2551 {
2552  struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
2553  VALUE ary;
2554 
2555  if (!tbl) return rb_ary_new2(0);
2556 
2557  ary = rb_ary_new2(rb_id_table_size(tbl));
2558  rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
2559  return ary;
2560 }
2561 
2562 void*
2564 {
2565  st_table *tbl = data;
2566  if (!tbl) {
2567  tbl = st_init_numtable();
2568  }
2569  if (RCLASS_CONST_TBL(mod)) {
2571  }
2572  return tbl;
2573 }
2574 
2575 void*
2577 {
2578  VALUE tmp = mod;
2579  for (;;) {
2580  data = rb_mod_const_at(tmp, data);
2581  tmp = RCLASS_SUPER(tmp);
2582  if (!tmp) break;
2583  if (tmp == rb_cObject && mod != rb_cObject) break;
2584  }
2585  return data;
2586 }
2587 
2588 static int
2589 list_i(st_data_t key, st_data_t value, VALUE ary)
2590 {
2591  ID sym = (ID)key;
2592  rb_const_entry_t *ce = (rb_const_entry_t *)value;
2593  if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
2594  return ST_CONTINUE;
2595 }
2596 
2597 VALUE
2598 rb_const_list(void *data)
2599 {
2600  st_table *tbl = data;
2601  VALUE ary;
2602 
2603  if (!tbl) return rb_ary_new2(0);
2604  ary = rb_ary_new2(tbl->num_entries);
2605  st_foreach_safe(tbl, list_i, ary);
2606  st_free_table(tbl);
2607 
2608  return ary;
2609 }
2610 
2611 /*
2612  * call-seq:
2613  * mod.constants(inherit=true) -> array
2614  *
2615  * Returns an array of the names of the constants accessible in
2616  * <i>mod</i>. This includes the names of constants in any included
2617  * modules (example at start of section), unless the <i>inherit</i>
2618  * parameter is set to <code>false</code>.
2619  *
2620  * The implementation makes no guarantees about the order in which the
2621  * constants are yielded.
2622  *
2623  * IO.constants.include?(:SYNC) #=> true
2624  * IO.constants(false).include?(:SYNC) #=> false
2625  *
2626  * Also see Module#const_defined?.
2627  */
2628 
2629 VALUE
2631 {
2632  bool inherit = true;
2633 
2634  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
2635 
2636  if (inherit) {
2637  return rb_const_list(rb_mod_const_of(mod, 0));
2638  }
2639  else {
2640  return rb_local_constants(mod);
2641  }
2642 }
2643 
2644 static int
2645 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2646 {
2647  VALUE tmp;
2648  int mod_retry = 0;
2649  rb_const_entry_t *ce;
2650 
2651  tmp = klass;
2652  retry:
2653  while (tmp) {
2654  if ((ce = rb_const_lookup(tmp, id))) {
2655  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2656  return (int)Qfalse;
2657  }
2658  if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
2659  !rb_autoloading_value(tmp, id, NULL, NULL))
2660  return (int)Qfalse;
2661 
2662  if (exclude && tmp == rb_cObject && klass != rb_cObject) {
2663  return (int)Qfalse;
2664  }
2665 
2666  return (int)Qtrue;
2667  }
2668  if (!recurse) break;
2669  tmp = RCLASS_SUPER(tmp);
2670  }
2671  if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
2672  mod_retry = 1;
2673  tmp = rb_cObject;
2674  goto retry;
2675  }
2676  return (int)Qfalse;
2677 }
2678 
2679 int
2681 {
2682  return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
2683 }
2684 
2685 int
2687 {
2688  return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
2689 }
2690 
2691 int
2693 {
2694  return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
2695 }
2696 
2699 {
2700  return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
2701 }
2702 
2703 static void
2704 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
2705 {
2707 }
2708 
2709 static void set_namespace_path(VALUE named_namespace, VALUE name);
2710 
2711 static enum rb_id_table_iterator_result
2712 set_namespace_path_i(ID id, VALUE v, void *payload)
2713 {
2715  VALUE value = ce->value;
2716  int has_permanent_classpath;
2717  VALUE parental_path = *((VALUE *) payload);
2718  if (!rb_is_const_id(id)) {
2719  return ID_TABLE_CONTINUE;
2720  }
2721  if (!rb_namespace_p(value)) {
2722  return ID_TABLE_CONTINUE;
2723  }
2724  classname(value, &has_permanent_classpath);
2725  if (has_permanent_classpath) {
2726  return ID_TABLE_CONTINUE;
2727  }
2728  set_namespace_path(value, build_const_path(parental_path, id));
2729  if (RCLASS_IV_TBL(value)) {
2730  st_data_t tmp = tmp_classpath;
2731  st_delete(RCLASS_IV_TBL(value), &tmp, 0);
2732  }
2733 
2734  return ID_TABLE_CONTINUE;
2735 }
2736 
2737 /*
2738  * Assign permanent classpaths to all namespaces that are directly or indirectly
2739  * nested under +named_namespace+. +named_namespace+ must have a permanent
2740  * classpath.
2741  */
2742 static void
2743 set_namespace_path(VALUE named_namespace, VALUE namespace_path)
2744 {
2745  struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
2746  if (!RCLASS_IV_TBL(named_namespace)) {
2747  RCLASS_IV_TBL(named_namespace) = st_init_numtable();
2748  }
2749  rb_class_ivar_set(named_namespace, classpath, namespace_path);
2750  if (const_table) {
2751  rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
2752  }
2753 }
2754 
2755 void
2757 {
2758  rb_const_entry_t *ce;
2759  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2760 
2761  if (NIL_P(klass)) {
2762  rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
2763  QUOTE_ID(id));
2764  }
2765 
2766  check_before_mod_set(klass, id, val, "constant");
2767  if (!tbl) {
2770  ce = ZALLOC(rb_const_entry_t);
2771  rb_id_table_insert(tbl, id, (VALUE)ce);
2772  setup_const_entry(ce, klass, val, CONST_PUBLIC);
2773  }
2774  else {
2775  struct autoload_const ac = {
2776  .mod = klass, .id = id,
2777  .value = val, .flag = CONST_PUBLIC,
2778  /* fill the rest with 0 */
2779  };
2780  const_tbl_update(&ac);
2781  }
2782  /*
2783  * Resolve and cache class name immediately to resolve ambiguity
2784  * and avoid order-dependency on const_tbl
2785  */
2786  if (rb_cObject && rb_namespace_p(val)) {
2787  int val_path_permanent;
2788  VALUE val_path = classname(val, &val_path_permanent);
2789  if (NIL_P(val_path) || !val_path_permanent) {
2790  if (klass == rb_cObject) {
2791  set_namespace_path(val, rb_id2str(id));
2792  }
2793  else {
2794  int parental_path_permanent;
2795  VALUE parental_path = classname(klass, &parental_path_permanent);
2796  if (!NIL_P(parental_path)) {
2797  if (parental_path_permanent && !val_path_permanent) {
2798  set_namespace_path(val, build_const_path(parental_path, id));
2799  }
2800  else if (!parental_path_permanent && NIL_P(val_path)) {
2801  rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
2802  }
2803  }
2804  }
2805  }
2806  }
2807 }
2808 
2809 static struct autoload_data_i *
2810 current_autoload_data(VALUE mod, ID id, struct autoload_const **acp)
2811 {
2812  struct autoload_data_i *ele;
2813  VALUE load = autoload_data(mod, id);
2814  if (!load) return 0;
2815  ele = get_autoload_data(load, acp);
2816  if (!ele) return 0;
2817  /* for autoloading thread, keep the defined value to autoloading storage */
2818  if (ele->state && (ele->state->thread == rb_thread_current())) {
2819  return ele;
2820  }
2821  return 0;
2822 }
2823 
2824 static void
2825 const_tbl_update(struct autoload_const *ac)
2826 {
2827  VALUE value;
2828  VALUE klass = ac->mod;
2829  VALUE val = ac->value;
2830  ID id = ac->id;
2831  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2832  rb_const_flag_t visibility = ac->flag;
2833  rb_const_entry_t *ce;
2834 
2835  if (rb_id_table_lookup(tbl, id, &value)) {
2836  ce = (rb_const_entry_t *)value;
2837  if (ce->value == Qundef) {
2838  struct autoload_data_i *ele = current_autoload_data(klass, id, &ac);
2839 
2840  if (ele) {
2842 
2843  ac->value = val; /* autoload_i is non-WB-protected */
2844  ac->file = rb_source_location(&ac->line);
2845  }
2846  else {
2847  /* otherwise autoloaded constant, allow to override */
2848  autoload_delete(klass, id);
2849  ce->flag = visibility;
2850  RB_OBJ_WRITE(klass, &ce->value, val);
2851  RB_OBJ_WRITE(klass, &ce->file, ac->file);
2852  ce->line = ac->line;
2853  }
2854  return;
2855  }
2856  else {
2857  VALUE name = QUOTE_ID(id);
2858  visibility = ce->flag;
2859  if (klass == rb_cObject)
2860  rb_warn("already initialized constant %"PRIsVALUE"", name);
2861  else
2862  rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
2864  if (!NIL_P(ce->file) && ce->line) {
2866  "previous definition of %"PRIsVALUE" was here", name);
2867  }
2868  }
2870  setup_const_entry(ce, klass, val, visibility);
2871  }
2872  else {
2874 
2875  ce = ZALLOC(rb_const_entry_t);
2876  rb_id_table_insert(tbl, id, (VALUE)ce);
2877  setup_const_entry(ce, klass, val, visibility);
2878  }
2879 }
2880 
2881 static void
2882 setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
2883  rb_const_flag_t visibility)
2884 {
2885  ce->flag = visibility;
2886  RB_OBJ_WRITE(klass, &ce->value, val);
2888 }
2889 
2890 void
2892 {
2893  ID id = rb_intern(name);
2894 
2895  if (!rb_is_const_id(id)) {
2896  rb_warn("rb_define_const: invalid name `%s' for constant", name);
2897  }
2899  rb_const_set(klass, id, val);
2900 }
2901 
2902 void
2904 {
2906 }
2907 
2908 static void
2909 set_const_visibility(VALUE mod, int argc, const VALUE *argv,
2911 {
2912  int i;
2913  rb_const_entry_t *ce;
2914  ID id;
2915 
2917  if (argc == 0) {
2918  rb_warning("%"PRIsVALUE" with no argument is just ignored",
2920  return;
2921  }
2922 
2923  for (i = 0; i < argc; i++) {
2924  struct autoload_const *ac;
2925  VALUE val = argv[i];
2926  id = rb_check_id(&val);
2927  if (!id) {
2928  if (i > 0) {
2930  }
2931 
2932  undefined_constant(mod, val);
2933  }
2934  if ((ce = rb_const_lookup(mod, id))) {
2935  ce->flag &= ~mask;
2936  ce->flag |= flag;
2937  if (ce->value == Qundef) {
2938  struct autoload_data_i *ele;
2939 
2940  ele = current_autoload_data(mod, id, &ac);
2941  if (ele) {
2942  ac->flag &= ~mask;
2943  ac->flag |= flag;
2944  }
2945  }
2946  }
2947  else {
2948  if (i > 0) {
2950  }
2951  undefined_constant(mod, ID2SYM(id));
2952  }
2953  }
2955 }
2956 
2957 void
2959 {
2960  rb_const_entry_t *ce;
2961  ID id;
2962  long len = strlen(name);
2963 
2965  if (!(id = rb_check_id_cstr(name, len, NULL))) {
2966  undefined_constant(mod, rb_fstring_new(name, len));
2967  }
2968  if (!(ce = rb_const_lookup(mod, id))) {
2969  undefined_constant(mod, ID2SYM(id));
2970  }
2971  ce->flag |= CONST_DEPRECATED;
2972 }
2973 
2974 /*
2975  * call-seq:
2976  * mod.private_constant(symbol, ...) => mod
2977  *
2978  * Makes a list of existing constants private.
2979  */
2980 
2981 VALUE
2983 {
2984  set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
2985  return obj;
2986 }
2987 
2988 /*
2989  * call-seq:
2990  * mod.public_constant(symbol, ...) => mod
2991  *
2992  * Makes a list of existing constants public.
2993  */
2994 
2995 VALUE
2997 {
2998  set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
2999  return obj;
3000 }
3001 
3002 /*
3003  * call-seq:
3004  * mod.deprecate_constant(symbol, ...) => mod
3005  *
3006  * Makes a list of existing constants deprecated. Attempt
3007  * to refer to them will produce a warning.
3008  *
3009  * module HTTP
3010  * NotFound = Exception.new
3011  * NOT_FOUND = NotFound # previous version of the library used this name
3012  *
3013  * deprecate_constant :NOT_FOUND
3014  * end
3015  *
3016  * HTTP::NOT_FOUND
3017  * # warning: constant HTTP::NOT_FOUND is deprecated
3018  *
3019  */
3020 
3021 VALUE
3023 {
3024  set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3025  return obj;
3026 }
3027 
3028 static VALUE
3029 original_module(VALUE c)
3030 {
3031  if (RB_TYPE_P(c, T_ICLASS))
3032  return RBASIC(c)->klass;
3033  return c;
3034 }
3035 
3036 static int
3037 cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3038 {
3039  if (!RCLASS_IV_TBL(klass)) return 0;
3040  return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v);
3041 }
3042 
3043 static VALUE
3044 cvar_front_klass(VALUE klass)
3045 {
3046  if (FL_TEST(klass, FL_SINGLETON)) {
3048  if (rb_namespace_p(obj)) {
3049  return obj;
3050  }
3051  }
3052  return RCLASS_SUPER(klass);
3053 }
3054 
3055 static void
3056 cvar_overtaken(VALUE front, VALUE target, ID id)
3057 {
3058  if (front && target != front) {
3059  st_data_t did = (st_data_t)id;
3060 
3061  if (RTEST(ruby_verbose) && original_module(front) != original_module(target)) {
3062  rb_warning("class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3063  ID2SYM(id), rb_class_name(original_module(front)),
3064  rb_class_name(original_module(target)));
3065  }
3066  if (BUILTIN_TYPE(front) == T_CLASS) {
3067  st_delete(RCLASS_IV_TBL(front), &did, 0);
3068  }
3069  }
3070 }
3071 
3072 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3073  for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3074  if (cvar_lookup_at(klass, id, (v))) { \
3075  r; \
3076  } \
3077  }
3078 
3079 #define CVAR_LOOKUP(v,r) do {\
3080  if (cvar_lookup_at(klass, id, (v))) {r;}\
3081  CVAR_FOREACH_ANCESTORS(klass, v, r);\
3082 } while(0)
3083 
3084 void
3086 {
3087  VALUE tmp, front = 0, target = 0;
3088 
3089  tmp = klass;
3090  CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3091  if (target) {
3092  cvar_overtaken(front, target, id);
3093  }
3094  else {
3095  target = tmp;
3096  }
3097 
3098  check_before_mod_set(target, id, val, "class variable");
3099  if (!RCLASS_IV_TBL(target)) {
3100  RCLASS_IV_TBL(target) = st_init_numtable();
3101  }
3102 
3103  rb_class_ivar_set(target, id, val);
3104 }
3105 
3106 VALUE
3108 {
3109  VALUE tmp, front = 0, target = 0;
3110  st_data_t value;
3111 
3112  tmp = klass;
3113  CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
3114  if (!target) {
3115  rb_name_err_raise("uninitialized class variable %1$s in %2$s",
3116  tmp, ID2SYM(id));
3117  }
3118  cvar_overtaken(front, target, id);
3119  return (VALUE)value;
3120 }
3121 
3122 VALUE
3124 {
3125  if (!klass) return Qfalse;
3126  CVAR_LOOKUP(0,return Qtrue);
3127  return Qfalse;
3128 }
3129 
3130 static ID
3131 cv_intern(VALUE klass, const char *name)
3132 {
3133  ID id = rb_intern(name);
3134  if (!rb_is_class_id(id)) {
3135  rb_name_err_raise("wrong class variable name %1$s",
3137  }
3138  return id;
3139 }
3140 
3141 void
3142 rb_cv_set(VALUE klass, const char *name, VALUE val)
3143 {
3144  ID id = cv_intern(klass, name);
3145  rb_cvar_set(klass, id, val);
3146 }
3147 
3148 VALUE
3149 rb_cv_get(VALUE klass, const char *name)
3150 {
3151  ID id = cv_intern(klass, name);
3152  return rb_cvar_get(klass, id);
3153 }
3154 
3155 void
3157 {
3158  ID id = cv_intern(klass, name);
3159  rb_cvar_set(klass, id, val);
3160 }
3161 
3162 static int
3163 cv_i(st_data_t k, st_data_t v, st_data_t a)
3164 {
3165  ID key = (ID)k;
3166  st_table *tbl = (st_table *)a;
3167 
3168  if (rb_is_class_id(key)) {
3169  st_update(tbl, (st_data_t)key, cv_i_update, 0);
3170  }
3171  return ST_CONTINUE;
3172 }
3173 
3174 static void*
3175 mod_cvar_at(VALUE mod, void *data)
3176 {
3177  st_table *tbl = data;
3178  if (!tbl) {
3179  tbl = st_init_numtable();
3180  }
3181  if (RCLASS_IV_TBL(mod)) {
3183  }
3184  return tbl;
3185 }
3186 
3187 static void*
3188 mod_cvar_of(VALUE mod, void *data)
3189 {
3190  VALUE tmp = mod;
3191  if (FL_TEST(mod, FL_SINGLETON)) {
3192  if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) {
3193  data = mod_cvar_at(tmp, data);
3194  tmp = cvar_front_klass(tmp);
3195  }
3196  }
3197  for (;;) {
3198  data = mod_cvar_at(tmp, data);
3199  tmp = RCLASS_SUPER(tmp);
3200  if (!tmp) break;
3201  }
3202  return data;
3203 }
3204 
3205 static int
3206 cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3207 {
3208  ID sym = (ID)key;
3209  rb_ary_push(ary, ID2SYM(sym));
3210  return ST_CONTINUE;
3211 }
3212 
3213 static VALUE
3214 cvar_list(void *data)
3215 {
3216  st_table *tbl = data;
3217  VALUE ary;
3218 
3219  if (!tbl) return rb_ary_new2(0);
3220  ary = rb_ary_new2(tbl->num_entries);
3221  st_foreach_safe(tbl, cv_list_i, ary);
3222  st_free_table(tbl);
3223 
3224  return ary;
3225 }
3226 
3227 /*
3228  * call-seq:
3229  * mod.class_variables(inherit=true) -> array
3230  *
3231  * Returns an array of the names of class variables in <i>mod</i>.
3232  * This includes the names of class variables in any included
3233  * modules, unless the <i>inherit</i> parameter is set to
3234  * <code>false</code>.
3235  *
3236  * class One
3237  * @@var1 = 1
3238  * end
3239  * class Two < One
3240  * @@var2 = 2
3241  * end
3242  * One.class_variables #=> [:@@var1]
3243  * Two.class_variables #=> [:@@var2, :@@var1]
3244  * Two.class_variables(false) #=> [:@@var2]
3245  */
3246 
3247 VALUE
3249 {
3250  bool inherit = true;
3251  st_table *tbl;
3252 
3253  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3254  if (inherit) {
3255  tbl = mod_cvar_of(mod, 0);
3256  }
3257  else {
3258  tbl = mod_cvar_at(mod, 0);
3259  }
3260  return cvar_list(tbl);
3261 }
3262 
3263 /*
3264  * call-seq:
3265  * remove_class_variable(sym) -> obj
3266  *
3267  * Removes the definition of the <i>sym</i>, returning that
3268  * constant's value.
3269  *
3270  * class Dummy
3271  * @@var = 99
3272  * puts @@var
3273  * remove_class_variable(:@@var)
3274  * p(defined? @@var)
3275  * end
3276  *
3277  * <em>produces:</em>
3278  *
3279  * 99
3280  * nil
3281  */
3282 
3283 VALUE
3285 {
3286  const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
3287  st_data_t val, n = id;
3288 
3289  if (!id) {
3290  not_defined:
3291  rb_name_err_raise("class variable %1$s not defined for %2$s",
3292  mod, name);
3293  }
3295  if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
3296  return (VALUE)val;
3297  }
3298  if (rb_cvar_defined(mod, id)) {
3299  rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
3300  }
3301  goto not_defined;
3302 }
3303 
3304 VALUE
3305 rb_iv_get(VALUE obj, const char *name)
3306 {
3308 
3309  if (!id) {
3310  if (RTEST(ruby_verbose))
3311  rb_warning("instance variable %s not initialized", name);
3312  return Qnil;
3313  }
3314  return rb_ivar_get(obj, id);
3315 }
3316 
3317 VALUE
3318 rb_iv_set(VALUE obj, const char *name, VALUE val)
3319 {
3320  ID id = rb_intern(name);
3321 
3322  return rb_ivar_set(obj, id, val);
3323 }
3324 
3325 /* tbl = xx(obj); tbl[key] = value; */
3326 int
3328 {
3329  st_table *tbl = RCLASS_IV_TBL(obj);
3330  int result = st_insert(tbl, (st_data_t)key, (st_data_t)value);
3331  RB_OBJ_WRITTEN(obj, Qundef, value);
3332  return result;
3333 }
3334 
3335 static int
3336 tbl_copy_i(st_data_t key, st_data_t value, st_data_t data)
3337 {
3338  RB_OBJ_WRITTEN((VALUE)data, Qundef, (VALUE)value);
3339  return ST_CONTINUE;
3340 }
3341 
3342 void
3344 {
3345  st_table *orig_tbl = RCLASS_IV_TBL(src);
3346  st_table *new_tbl = st_copy(orig_tbl);
3347  st_foreach(new_tbl, tbl_copy_i, (st_data_t)dst);
3348  RCLASS_IV_TBL(dst) = new_tbl;
3349 }
3350 
3353 {
3354  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3355  VALUE val;
3356 
3357  if (tbl && rb_id_table_lookup(tbl, id, &val)) {
3358  return (rb_const_entry_t *)val;
3359  }
3360  return 0;
3361 }
list_empty
#define list_empty(h)
Definition: rb_mjit_min_header-2.7.2.h:9072
rb_f_untrace_var
VALUE rb_f_untrace_var(int argc, const VALUE *argv)
Definition: variable.c:574
st_foreach_safe
void st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
Definition: hash.c:1294
rb_gv_set
VALUE rb_gv_set(const char *name, VALUE val)
Definition: variable.c:671
rb_mod_const_of
void * rb_mod_const_of(VALUE mod, void *data)
Definition: variable.c:2576
obj_ivar_tag
Definition: variable.c:1349
rb_class_ivar_set
int rb_class_ivar_set(VALUE obj, ID key, VALUE value)
Definition: variable.c:3327
ID
unsigned long ID
Definition: ruby.h:103
rb_ivar_set_internal
void rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
Definition: variable.c:1308
rb_ivar_count
st_index_t rb_ivar_count(VALUE obj)
Definition: variable.c:1511
rb_define_class_variable
void rb_define_class_variable(VALUE klass, const char *name, VALUE val)
Definition: variable.c:3156
rb_const_defined
int rb_const_defined(VALUE klass, ID id)
Definition: variable.c:2686
rb_sourcefile
const char * rb_sourcefile(void)
Definition: vm.c:1331
rb_is_const_id
int rb_is_const_id(ID id)
Definition: symbol.c:854
constant.h
rb_fstring
VALUE rb_fstring(VALUE)
Definition: string.c:312
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
TRUE
#define TRUE
Definition: nkf.h:175
rb_gvar_var_setter
void rb_gvar_var_setter(VALUE val, ID id, VALUE *data)
Definition: variable.c:400
rb_free_generic_ivar
void rb_free_generic_ivar(VALUE obj)
Definition: variable.c:993
CVAR_LOOKUP
#define CVAR_LOOKUP(v, r)
Definition: variable.c:3079
rb_mod_const_at
void * rb_mod_const_at(VALUE mod, void *data)
Definition: variable.c:2563
list_del_init
#define list_del_init(n)
Definition: rb_mjit_min_header-2.7.2.h:9090
rb_check_id
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
trace_var::next
struct trace_var * next
Definition: variable.c:298
ROBJ_TRANSIENT_SET
#define ROBJ_TRANSIENT_SET(obj)
Definition: internal.h:2263
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
st_copy
st_table * st_copy(st_table *old_tab)
Definition: st.c:1320
rb_cvar_get
VALUE rb_cvar_get(VALUE klass, ID id)
Definition: variable.c:3107
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
trace_data::trace
struct trace_var * trace
Definition: variable.c:626
rb_obj_hide
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
autoload_state
Definition: variable.c:1812
assert
#define assert(x)
Definition: dlmalloc.c:1176
rb_thread_wakeup_alive
VALUE rb_thread_wakeup_alive(VALUE)
Definition: thread.c:2549
rb_class_modify_check
void rb_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
Definition: eval.c:438
id
const int id
Definition: nkf.c:209
st_table::num_entries
st_index_t num_entries
Definition: st.h:86
Init_var_tables
void Init_var_tables(void)
Definition: variable.c:48
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
rb_feature_provided
int rb_feature_provided(const char *, const char **)
Definition: load.c:519
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7066
rb_gvar_setter_function_of
rb_gvar_setter_t * rb_gvar_setter_function_of(const struct rb_global_entry *entry)
Definition: variable.c:708
rb_id_table_size
size_t rb_id_table_size(const struct rb_id_table *tbl)
Definition: id_table.c:117
rb_match_count
int rb_match_count(VALUE match)
Definition: re.c:1299
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:315
rb_vm_inc_const_missing_count
void rb_vm_inc_const_missing_count(void)
Definition: vm.c:386
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Definition: variable.c:1447
rb_gc_update_tbl_refs
void rb_gc_update_tbl_refs(st_table *ptr)
Definition: gc.c:7986
rb_gvar_undef_marker
void rb_gvar_undef_marker(VALUE *var)
Definition: variable.c:368
rb_global_entry::var
struct rb_global_variable * var
Definition: internal.h:1351
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:336
rb_ivar_defined
VALUE rb_ivar_defined(VALUE obj, ID id)
Definition: variable.c:1317
RB_BUILTIN_TYPE
#define RB_BUILTIN_TYPE(x)
Definition: ruby.h:550
CONST_PUBLIC
@ CONST_PUBLIC
Definition: constant.h:18
int
__inline__ int
Definition: rb_mjit_min_header-2.7.2.h:2877
ivar_update::iv_index_tbl
st_table * iv_index_tbl
Definition: variable.c:40
ST_STOP
@ ST_STOP
Definition: st.h:99
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE mod, VALUE name)
Definition: variable.c:2483
st_is_member
#define st_is_member(table, key)
Definition: st.h:97
rb_const_source_location_at
MJIT_FUNC_EXPORTED VALUE rb_const_source_location_at(VALUE klass, ID id)
Definition: variable.c:2467
rb_mark_tbl_no_pin
void rb_mark_tbl_no_pin(st_table *tbl)
Definition: gc.c:5014
autoload_const::file
VALUE file
Definition: variable.c:1805
rb_warning_category_enabled_p
MJIT_FUNC_EXPORTED bool rb_warning_category_enabled_p(rb_warning_category_t category)
Definition: error.c:166
rb_gvar_undef_getter
VALUE rb_gvar_undef_getter(ID id, VALUE *_)
Definition: variable.c:349
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5499
autoload_const::cnode
struct list_node cnode
Definition: variable.c:1801
rb_autoload_str
void rb_autoload_str(VALUE mod, ID id, VALUE file)
Definition: variable.c:1937
RB_CONST_PRIVATE_P
#define RB_CONST_PRIVATE_P(ce)
Definition: constant.h:23
rb_global_entry
MJIT_FUNC_EXPORTED struct rb_global_entry * rb_global_entry(ID id)
Definition: variable.c:326
rb_const_entry_struct::line
int line
Definition: constant.h:33
autoload_data_i
Definition: variable.c:1819
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2037
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
rb_cvar_set
void rb_cvar_set(VALUE klass, ID id, VALUE val)
Definition: variable.c:3085
rb_mark_generic_ivar
void rb_mark_generic_ivar(VALUE obj)
Definition: variable.c:973
trace_data::val
VALUE val
Definition: variable.c:627
VALUE
unsigned long VALUE
Definition: ruby.h:102
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_eArgError
VALUE rb_eArgError
Definition: error.c:925
encoding.h
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
rb_intern
#define rb_intern(str)
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
st_delete
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1418
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
autoload_state::result
VALUE result
Definition: variable.c:1814
rb_gc_mark_global_tbl
void rb_gc_mark_global_tbl(void)
Definition: variable.c:434
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:8114
rb_cModule
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:2034
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2676
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_const_entry_struct::value
VALUE value
Definition: constant.h:34
st_add_direct
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1251
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
rb_id_table_iterator_result
rb_id_table_iterator_result
Definition: id_table.h:8
rb_path2class
VALUE rb_path2class(const char *path)
Definition: variable.c:268
id.h
rb_const_flag_t
rb_const_flag_t
Definition: constant.h:14
rb_id_table
Definition: id_table.c:40
rb_id_table_insert
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
Definition: id_table.c:256
list_add_tail
#define list_add_tail(h, n)
Definition: rb_mjit_min_header-2.7.2.h:9065
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_autoload
RUBY_FUNC_EXPORTED void rb_autoload(VALUE mod, ID id, const char *file)
Definition: variable.c:1928
rb_define_readonly_variable
void rb_define_readonly_variable(const char *name, const VALUE *var)
Definition: variable.c:505
rb_gvar_getter_t
VALUE rb_gvar_getter_t(ID id, VALUE *data)
Definition: ruby.h:1782
Qundef
#define Qundef
Definition: ruby.h:470
rb_cvar_defined
VALUE rb_cvar_defined(VALUE klass, ID id)
Definition: variable.c:3123
id_for_var
#define id_for_var(obj, name, part, type)
Definition: variable.c:1590
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
rb_const_set
void rb_const_set(VALUE klass, ID id, VALUE val)
Definition: variable.c:2756
rb_eNameError
VALUE rb_eNameError
Definition: error.c:929
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
rb_global_variable::getter
rb_gvar_getter_t * getter
Definition: variable.c:305
ptr
struct RIMemo * ptr
Definition: debug.c:65
list_for_each_safe
#define list_for_each_safe(h, i, nxt, member)
Definition: rb_mjit_min_header-2.7.2.h:9139
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_attr_delete
VALUE rb_attr_delete(VALUE obj, ID id)
Definition: variable.c:1126
rb_gvar_setter_t
void rb_gvar_setter_t(VALUE val, ID id, VALUE *data)
Definition: ruby.h:1783
rb_name_error
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:1515
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
rb_gvar_set
MJIT_FUNC_EXPORTED VALUE rb_gvar_set(struct rb_global_entry *entry, VALUE val)
Definition: variable.c:654
rb_match_nth_defined
int rb_match_nth_defined(int nth, VALUE match)
Definition: re.c:1309
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:104
st.h
rb_path_to_class
VALUE rb_path_to_class(VALUE pathname)
Definition: variable.c:226
NULL
#define NULL
Definition: _sdbm.c:101
rb_const_source_location
VALUE rb_const_source_location(VALUE klass, ID id)
Definition: variable.c:2461
rb_const_list
VALUE rb_const_list(void *data)
Definition: variable.c:2598
rb_gvar_var_marker
void rb_gvar_var_marker(VALUE *var)
Definition: variable.c:406
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
check_autoload_table
#define check_autoload_table(av)
Definition: variable.c:1783
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_mod_constants
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
Definition: variable.c:2630
FL_SET
#define FL_SET(x, f)
Definition: ruby.h:1359
rb_gvar_marker_t
void rb_gvar_marker_t(VALUE *var)
Definition: ruby.h:1784
rb_autoloading_value
MJIT_FUNC_EXPORTED int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag)
Definition: variable.c:2078
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_define_hooked_variable
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Definition: variable.c:480
gen_ivar_tag::arg
st_data_t arg
Definition: variable.c:1388
gen_ivtbl::ivptr
VALUE ivptr[FLEX_ARY_LEN]
Definition: variable.h:6
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_alias_variable
void rb_alias_variable(ID name1, ID name2)
Definition: variable.c:756
T_OBJECT
#define T_OBJECT
Definition: ruby.h:523
rb_const_entry_struct::flag
rb_const_flag_t flag
Definition: constant.h:32
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
trace_var
Definition: variable.c:294
autoload_state::ac
struct autoload_const * ac
Definition: variable.c:1813
rb_is_class_id
int rb_is_class_id(ID id)
Definition: symbol.c:860
ASSUME
#define ASSUME(x)
Definition: ruby.h:52
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
obj_ivar_tag::obj
VALUE obj
Definition: variable.c:1350
givar_copy::iv_index_tbl
st_table * iv_index_tbl
Definition: variable.c:1422
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
CONST_PRIVATE
@ CONST_PRIVATE
Definition: constant.h:19
rb_global_variable::data
VALUE * data
Definition: variable.c:304
void
void
Definition: rb_mjit_min_header-2.7.2.h:13321
autoload_data_i::fork_gen
rb_serial_t fork_gen
Definition: variable.c:1822
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
rb_f_global_variables
VALUE rb_f_global_variables(void)
Definition: variable.c:728
rb_thread_sleep_deadly
void rb_thread_sleep_deadly(void)
Definition: thread.c:1321
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
rb_global_variable::marker
rb_gvar_marker_t * marker
Definition: variable.c:307
rb_global_entry::id
ID id
Definition: internal.h:1352
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
rb_autoload_load
VALUE rb_autoload_load(VALUE mod, ID id)
Definition: variable.c:2226
autoload_state::waitq
struct list_node waitq
Definition: variable.c:1816
rb_ivar_lookup
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
Definition: variable.c:1035
rb_autoload_at_p
VALUE rb_autoload_at_p(VALUE mod, ID id, int recur)
Definition: variable.c:2291
RCLASS_IV_INDEX_TBL
#define RCLASS_IV_INDEX_TBL(c)
Definition: internal.h:1074
rb_gc_mark_maybe
void rb_gc_mark_maybe(VALUE obj)
Definition: gc.c:5047
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
rb_vm_pop_cfunc_frame
MJIT_STATIC void rb_vm_pop_cfunc_frame(void)
Definition: rb_mjit_min_header-2.7.2.h:17331
rb_id_table_foreach
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
Definition: id_table.c:292
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.2.h:13302
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
rb_gvar_undef_setter
void rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
Definition: variable.c:357
id_for_var_message
#define id_for_var_message(obj, name, type, message)
Definition: variable.c:1592
RCLASS_CONST_TBL
#define RCLASS_CONST_TBL(c)
Definition: internal.h:1067
rb_iv_get
VALUE rb_iv_get(VALUE obj, const char *name)
Definition: variable.c:3305
rb_search_class_path
VALUE rb_search_class_path(VALUE klass)
Definition: variable.c:175
rb_const_defined_at
int rb_const_defined_at(VALUE klass, ID id)
Definition: variable.c:2692
list_head
Definition: rb_mjit_min_header-2.7.2.h:9018
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_f_trace_var
VALUE rb_f_trace_var(int argc, const VALUE *argv)
Definition: variable.c:528
int32_t
__int32_t int32_t
Definition: rb_mjit_min_header-2.7.2.h:1179
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
FL_EXIVAR
#define FL_EXIVAR
Definition: ruby.h:1286
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3347
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
rb_generic_ivar_memsize
RUBY_FUNC_EXPORTED size_t rb_generic_ivar_memsize(VALUE obj)
Definition: variable.c:1010
OnigEncodingTypeST
Definition: onigmo.h:160
sym
#define sym(x)
Definition: date_core.c:3716
rb_clear_constant_cache
void rb_clear_constant_cache(void)
Definition: vm_method.c:87
ivar_update::iv_extended
int iv_extended
Definition: variable.c:44
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
trace_var::func
void(* func)(VALUE arg, VALUE val)
Definition: variable.c:296
rb_mod_deprecate_constant
VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:3022
rb_set_class_path_string
void rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
Definition: variable.c:198
rb_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.2.h:7759
FL_UNSET
#define FL_UNSET(x, f)
Definition: ruby.h:1361
rb_ivar_foreach_callback_func
int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg)
Definition: variable.c:1347
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
gen_ivar_tag
Definition: variable.c:1385
rb_obj_remove_instance_variable
VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name)
Definition: variable.c:1634
gen_ivar_tag::ivtbl
struct gen_ivtbl * ivtbl
Definition: variable.c:1386
trace_var::removed
int removed
Definition: variable.c:295
transient_heap.h
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
vm_core.h
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:924
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
autoload_const::flag
rb_const_flag_t flag
Definition: variable.c:1807
T_CLASS
#define T_CLASS
Definition: ruby.h:524
rb_obj_transient_heap_evacuate
void rb_obj_transient_heap_evacuate(VALUE obj, int promote)
Definition: variable.c:1215
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:922
rb_gvar_is_traced
bool rb_gvar_is_traced(const struct rb_global_entry *entry)
Definition: variable.c:714
rb_class_path_cached
VALUE rb_class_path_cached(VALUE klass)
Definition: variable.c:162
rb_gvar_val_setter
void rb_gvar_val_setter(VALUE val, ID id, VALUE *_)
Definition: variable.c:379
rb_attr_get
VALUE rb_attr_get(VALUE obj, ID id)
Definition: variable.c:1084
mod
#define mod(x, y)
Definition: date_strftime.c:28
rb_eval_cmd_kw
VALUE rb_eval_cmd_kw(VALUE, VALUE, int)
Definition: vm_eval.c:1801
rb_transient_heap_alloc
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
Definition: transient_heap.c:359
ROBJECT_IVPTR
#define ROBJECT_IVPTR(o)
Definition: ruby.h:937
autoload_const
Definition: variable.c:1800
rb_is_instance_id
int rb_is_instance_id(ID id)
Definition: symbol.c:872
FALSE
#define FALSE
Definition: nkf.h:174
rb_backref_get
VALUE rb_backref_get(void)
Definition: vm.c:1304
ivar_update::ivtbl
struct gen_ivtbl * ivtbl
Definition: variable.c:41
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
rb_gc_mark_movable
void rb_gc_mark_movable(VALUE ptr)
Definition: gc.c:5209
rb_set_class_path
void rb_set_class_path(VALUE klass, VALUE under, const char *name)
Definition: variable.c:218
gen_ivtbl::numiv
uint32_t numiv
Definition: variable.h:5
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.2.h:5636
rb_class2name
const char * rb_class2name(VALUE klass)
Definition: variable.c:280
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
rb_gvar_val_marker
void rb_gvar_val_marker(VALUE *var)
Definition: variable.c:386
rb_gvar_var_getter
VALUE rb_gvar_var_getter(ID id, VALUE *var)
Definition: variable.c:393
rb_public_const_get_at
MJIT_FUNC_EXPORTED VALUE rb_public_const_get_at(VALUE klass, ID id)
Definition: variable.c:2409
rb_define_variable
void rb_define_variable(const char *name, VALUE *var)
Definition: variable.c:499
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
ROBJECT
#define ROBJECT(obj)
Definition: ruby.h:1268
ROBJ_TRANSIENT_UNSET
#define ROBJ_TRANSIENT_UNSET(obj)
Definition: internal.h:2264
rb_fstring_new
VALUE rb_fstring_new(const char *ptr, long len)
Definition: string.c:396
mask
enum @0::@2::@3 mask
st_update
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1510
variable.h
key
key
Definition: openssl_missing.h:181
rb_global_variable::block_trace
int block_trace
Definition: variable.c:303
RCLASS_IV_TBL
#define RCLASS_IV_TBL(c)
Definition: internal.h:1066
rb_ivar_set
VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
Definition: variable.c:1300
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.2.h:6407
ivar_update
Definition: variable.c:38
RB_CONST_DEPRECATED_P
#define RB_CONST_DEPRECATED_P(ce)
Definition: constant.h:28
RCLASS_EXT
#define RCLASS_EXT(c)
Definition: classext.h:15
rb_frame_callee
ID rb_frame_callee(void)
The name of the current method.
Definition: eval.c:1200
QUOTE_ID
#define QUOTE_ID(id)
Definition: internal.h:2149
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
T_MODULE
#define T_MODULE
Definition: ruby.h:526
list_del
#define list_del(n)
Definition: rb_mjit_min_header-2.7.2.h:9083
rb_iv_tbl_copy
void rb_iv_tbl_copy(VALUE dst, VALUE src)
Definition: variable.c:3343
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
rb_const_remove
VALUE rb_const_remove(VALUE mod, ID id)
Definition: variable.c:2494
rb_const_missing
VALUE rb_const_missing(VALUE klass, VALUE name)
Definition: variable.c:1694
rb_ivar_get
VALUE rb_ivar_get(VALUE obj, ID id)
Definition: variable.c:1070
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_const_lookup
MJIT_FUNC_EXPORTED rb_const_entry_t * rb_const_lookup(VALUE klass, ID id)
Definition: variable.c:3352
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
rb_const_get_from
VALUE rb_const_get_from(VALUE klass, ID id)
Definition: variable.c:2385
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.2.h:5777
rb_intern2
ID rb_intern2(const char *, long)
Definition: symbol.c:653
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
internal.h
autoload_data_i::constants
struct list_head constants
Definition: variable.c:1823
ROBJ_TRANSIENT_P
#define ROBJ_TRANSIENT_P(obj)
Definition: internal.h:2262
argv
char ** argv
Definition: ruby.c:223
autoload_const::id
ID id
Definition: variable.c:1806
rb_define_global_const
void rb_define_global_const(const char *name, VALUE val)
Definition: variable.c:2903
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
xmalloc
#define xmalloc
Definition: defines.h:211
xrealloc
#define xrealloc
Definition: defines.h:214
autoload_const::ad
VALUE ad
Definition: variable.c:1803
RB_CONST_PUBLIC_P
#define RB_CONST_PUBLIC_P(ce)
Definition: constant.h:25
rb_autoload_p
VALUE rb_autoload_p(VALUE mod, ID id)
Definition: variable.c:2285
trace_data
Definition: variable.c:625
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
rb_gvar_val_getter
VALUE rb_gvar_val_getter(ID id, VALUE *data)
Definition: variable.c:373
rb_gvar_getter_function_of
rb_gvar_getter_t * rb_gvar_getter_function_of(const struct rb_global_entry *entry)
Definition: variable.c:702
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
autoload_const::value
VALUE value
Definition: variable.c:1804
rb_ivar_foreach
void rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
Definition: variable.c:1489
rb_public_const_get_from
MJIT_FUNC_EXPORTED VALUE rb_public_const_get_from(VALUE klass, ID id)
Definition: variable.c:2403
givar_copy
Definition: variable.c:1420
rb_obj_instance_variables
VALUE rb_obj_instance_variables(VALUE obj)
Definition: variable.c:1579
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
autoload_data_i::state
struct autoload_state * state
Definition: variable.c:1821
autoload_state::thread
VALUE thread
Definition: variable.c:1815
obj_ivar_tag::arg
st_data_t arg
Definition: variable.c:1352
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.2.h:2874
fallback_func
VALUE(* fallback_func)(VALUE obj, VALUE name)
Definition: variable.c:127
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
debug_counter.h
rb_mv_generic_ivar
void rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
Definition: variable.c:983
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_const_get
VALUE rb_const_get(VALUE klass, ID id)
Definition: variable.c:2391
path
VALUE path
Definition: rb_mjit_min_header-2.7.2.h:7389
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2852
rb_global_variable::setter
rb_gvar_setter_t * setter
Definition: variable.c:306
rb_global_variable::counter
int counter
Definition: variable.c:302
rb_deprecate_constant
void rb_deprecate_constant(VALUE mod, const char *name)
Definition: variable.c:2958
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_const_warn_if_deprecated
MJIT_FUNC_EXPORTED void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
Definition: variable.c:2307
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.2.h:6620
rb_hash_delete
VALUE rb_hash_delete(VALUE hash, VALUE key)
Definition: hash.c:2344
rb_id_table_create
struct rb_id_table * rb_id_table_create(size_t capa)
Definition: id_table.c:95
rb_check_id_cstr
ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:988
argc
int argc
Definition: ruby.c:222
rb_obj_classname
const char * rb_obj_classname(VALUE obj)
Definition: variable.c:289
REALLOC_N
#define REALLOC_N(var, type, n)
Definition: ruby.h:1667
rb_name_error_str
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:1530
list_node
Definition: rb_mjit_min_header-2.7.2.h:9014
rb_define_const
void rb_define_const(VALUE klass, const char *name, VALUE val)
Definition: variable.c:2891
RB_NO_KEYWORDS
#define RB_NO_KEYWORDS
Definition: ruby.h:1977
rb_cv_set
void rb_cv_set(VALUE klass, const char *name, VALUE val)
Definition: variable.c:3142
recur
#define recur(fmt)
Definition: date_strptime.c:152
rb_thread_to_be_killed
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2472
ROBJECT_EMBED_LEN_MAX
@ ROBJECT_EMBED_LEN_MAX
Definition: ruby.h:916
rb_data_type_struct
Definition: ruby.h:1148
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
rb_name_err_raise_str
#define rb_name_err_raise_str(mesg, recv, name)
Definition: internal.h:1575
rb_global_variable
Definition: variable.c:301
xfree
#define xfree
Definition: defines.h:216
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.2.h:5398
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
rb_mod_remove_cvar
VALUE rb_mod_remove_cvar(VALUE mod, VALUE name)
Definition: variable.c:3284
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5215
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
autoload_data_i::feature
VALUE feature
Definition: variable.c:1820
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:891
_
#define _(args)
Definition: dln.h:28
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.2.h:4087
count
int count
Definition: encoding.c:57
rb_compile_warn
void rb_compile_warn(const char *file, int line, const char *fmt,...)
Definition: error.c:272
rb_gvar_defined
MJIT_FUNC_EXPORTED VALUE rb_gvar_defined(struct rb_global_entry *entry)
Definition: variable.c:695
rb_const_defined_from
int rb_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2680
st_memsize
size_t st_memsize(const st_table *tab)
Definition: st.c:719
Qtrue
#define Qtrue
Definition: ruby.h:468
NORETURN
NORETURN(static void uninitialized_constant(VALUE, VALUE))
QUOTE
#define QUOTE(str)
Definition: internal.h:2148
v
int VALUE v
Definition: rb_mjit_min_header-2.7.2.h:12380
len
uint8_t len
Definition: escape.c:17
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition: debug_counter.h:375
rb_const_entry_struct::file
VALUE file
Definition: constant.h:35
CONST_VISIBILITY_MASK
@ CONST_VISIBILITY_MASK
Definition: constant.h:17
rb_class_path
VALUE rb_class_path(VALUE klass)
Definition: variable.c:153
ROBJECT_NUMIV
#define ROBJECT_NUMIV(o)
Definition: ruby.h:933
rb_mod_private_constant
VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:2982
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_class_name
VALUE rb_class_name(VALUE klass)
Definition: variable.c:274
autoload_const::mod
VALUE mod
Definition: variable.c:1802
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.2.h:7940
autoload_const::line
int line
Definition: variable.c:1808
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
idConst_missing
@ idConst_missing
Definition: rb_mjit_min_header-2.7.2.h:8733
old
VALUE ID VALUE old
Definition: rb_mjit_min_header-2.7.2.h:16196
index
int index
Definition: rb_mjit_min_header-2.7.2.h:11294
rb_mod_class_variables
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
Definition: variable.c:3248
rb_id_table_foreach_values
void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data)
Definition: id_table.c:311
rb_gv_get
VALUE rb_gv_get(const char *name)
Definition: variable.c:680
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.2.h:6152
rb_public_const_defined_from
MJIT_FUNC_EXPORTED int rb_public_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2698
givar_copy::obj
VALUE obj
Definition: variable.c:1421
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1115
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
RB_WARN_CATEGORY_DEPRECATED
@ RB_WARN_CATEGORY_DEPRECATED
Definition: internal.h:1562
gen_ivtbl
Definition: variable.h:4
rb_define_virtual_variable
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Definition: variable.c:511
ROBJECT_EMBED
@ ROBJECT_EMBED
Definition: ruby.h:917
Qnil
#define Qnil
Definition: ruby.h:469
rb_id_table_delete
int rb_id_table_delete(struct rb_id_table *tbl, ID id)
Definition: id_table.c:262
ivar_update::u
union ivar_update::@0 u
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
gen_ivar_tag::func
rb_ivar_foreach_callback_func * func
Definition: variable.c:1387
rb_id_table_lookup
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
Definition: id_table.c:226
rb_mod_name
VALUE rb_mod_name(VALUE mod)
Definition: variable.c:102
rb_cv_get
VALUE rb_cv_get(VALUE klass, const char *name)
Definition: variable.c:3149
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
util.h
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1577
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN(val)
Definition: ruby.h:59
CONST_DEPRECATED
@ CONST_DEPRECATED
Definition: constant.h:15
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_global_variable::trace
struct trace_var * trace
Definition: variable.c:308
rb_mod_public_constant
VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:2996
st_free_table
void st_free_table(st_table *tab)
Definition: st.c:709
char
#define char
Definition: rb_mjit_min_header-2.7.2.h:2916
st_table
Definition: st.h:79
rb_const_get_at
VALUE rb_const_get_at(VALUE klass, ID id)
Definition: variable.c:2397
rb_mod_const_missing
VALUE rb_mod_const_missing(VALUE klass, VALUE name)
Definition: variable.c:1739
ID_TABLE_CONTINUE
@ ID_TABLE_CONTINUE
Definition: id_table.h:9
id__attached__
@ id__attached__
Definition: rb_mjit_min_header-2.7.2.h:8750
rb_const_entry_struct
Definition: constant.h:31
id_table.h
rb_ivar_generic_ivtbl
MJIT_FUNC_EXPORTED struct st_table * rb_ivar_generic_ivtbl(void)
Definition: variable.c:803
RTEST
#define RTEST(v)
Definition: ruby.h:481
ivar_update::index
st_data_t index
Definition: variable.c:43
RB_SPECIAL_CONST_P
#define RB_SPECIAL_CONST_P(x)
Definition: ruby.h:1312
rb_iv_set
VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
Definition: variable.c:3318
strcmp
int strcmp(const char *, const char *)
trace_var::data
VALUE data
Definition: variable.c:297
rb_global_entry
Definition: internal.h:1350
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
ROBJECT_IV_INDEX_TBL
#define ROBJECT_IV_INDEX_TBL(o)
Definition: ruby.h:941
obj_ivar_tag::func
rb_ivar_foreach_callback_func * func
Definition: variable.c:1351
rb_gvar_get
MJIT_FUNC_EXPORTED VALUE rb_gvar_get(struct rb_global_entry *entry)
Definition: variable.c:619
givar_copy::ivtbl
struct gen_ivtbl * ivtbl
Definition: variable.c:1423
rb_source_location
VALUE rb_source_location(int *pline)
Definition: vm.c:1360
rb_class_real
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
Definition: object.c:202
name
const char * name
Definition: nkf.c:208
n
const char size_t n
Definition: rb_mjit_min_header-2.7.2.h:5491
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837