Ruby  2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)
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 */
1807 };
1808 
1809 /* always on stack, no need to mark */
1815 };
1816 
1819  struct autoload_state *state; /* points to on-stack struct */
1821  struct list_head constants; /* <=> autoload_const.cnode */
1822 };
1823 
1824 static void
1825 autoload_i_compact(void *ptr)
1826 {
1827  struct autoload_data_i *p = ptr;
1828  p->feature = rb_gc_location(p->feature);
1829 }
1830 
1831 static void
1832 autoload_i_mark(void *ptr)
1833 {
1834  struct autoload_data_i *p = ptr;
1835 
1837 
1838  /* allow GC to free us if no modules refer to this via autoload_const.ad */
1839  if (list_empty(&p->constants)) {
1840  rb_hash_delete(autoload_featuremap, p->feature);
1841  }
1842 }
1843 
1844 static void
1845 autoload_i_free(void *ptr)
1846 {
1847  struct autoload_data_i *p = ptr;
1848 
1849  /* we may leak some memory at VM shutdown time, no big deal */
1850  if (list_empty(&p->constants)) {
1851  xfree(p);
1852  }
1853 }
1854 
1855 static size_t
1856 autoload_i_memsize(const void *ptr)
1857 {
1858  return sizeof(struct autoload_data_i);
1859 }
1860 
1861 static const rb_data_type_t autoload_data_i_type = {
1862  "autoload_i",
1863  {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact},
1865 };
1866 
1867 static void
1868 autoload_c_compact(void *ptr)
1869 {
1870  struct autoload_const *ac = ptr;
1871 
1872  ac->mod = rb_gc_location(ac->mod);
1873  ac->ad = rb_gc_location(ac->ad);
1874  ac->value = rb_gc_location(ac->value);
1875 }
1876 
1877 static void
1878 autoload_c_mark(void *ptr)
1879 {
1880  struct autoload_const *ac = ptr;
1881 
1882  rb_gc_mark_movable(ac->mod);
1883  rb_gc_mark_movable(ac->ad);
1885 }
1886 
1887 static void
1888 autoload_c_free(void *ptr)
1889 {
1890  struct autoload_const *ac = ptr;
1891  list_del(&ac->cnode);
1892  xfree(ac);
1893 }
1894 
1895 static size_t
1896 autoload_c_memsize(const void *ptr)
1897 {
1898  return sizeof(struct autoload_const);
1899 }
1900 
1901 static const rb_data_type_t autoload_const_type = {
1902  "autoload_const",
1903  {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
1905 };
1906 
1907 static struct autoload_data_i *
1908 get_autoload_data(VALUE acv, struct autoload_const **acp)
1909 {
1910  struct autoload_const *ac = rb_check_typeddata(acv, &autoload_const_type);
1911  struct autoload_data_i *ele;
1912 
1913  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
1914  /* do not reach across stack for ->state after forking: */
1915  if (ele && ele->state && ele->fork_gen != GET_VM()->fork_gen) {
1916  ele->state = 0;
1917  ele->fork_gen = 0;
1918  }
1919  if (acp) *acp = ac;
1920  return ele;
1921 }
1922 
1923 RUBY_FUNC_EXPORTED void
1924 rb_autoload(VALUE mod, ID id, const char *file)
1925 {
1926  if (!file || !*file) {
1927  rb_raise(rb_eArgError, "empty file name");
1928  }
1929  rb_autoload_str(mod, id, rb_fstring_cstr(file));
1930 }
1931 
1932 void
1934 {
1935  st_data_t av;
1936  VALUE ad;
1937  struct st_table *tbl;
1938  struct autoload_data_i *ele;
1939  rb_const_entry_t *ce;
1940 
1941  if (!rb_is_const_id(id)) {
1942  rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"",
1943  QUOTE_ID(id));
1944  }
1945 
1946  Check_Type(file, T_STRING);
1947  if (!RSTRING_LEN(file)) {
1948  rb_raise(rb_eArgError, "empty file name");
1949  }
1950 
1951  ce = rb_const_lookup(mod, id);
1952  if (ce && ce->value != Qundef) {
1953  return;
1954  }
1955 
1956  rb_const_set(mod, id, Qundef);
1957  tbl = RCLASS_IV_TBL(mod);
1958  if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
1959  tbl = check_autoload_table((VALUE)av);
1960  }
1961  else {
1962  if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
1963  av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
1964  st_add_direct(tbl, (st_data_t)autoload, av);
1965  RB_OBJ_WRITTEN(mod, Qnil, av);
1966  DATA_PTR(av) = tbl = st_init_numtable();
1967  }
1968 
1969  file = rb_fstring(file);
1970  if (!autoload_featuremap) {
1971  autoload_featuremap = rb_ident_hash_new();
1972  rb_obj_hide(autoload_featuremap);
1973  rb_gc_register_mark_object(autoload_featuremap);
1974  }
1975  ad = rb_hash_aref(autoload_featuremap, file);
1976  if (NIL_P(ad)) {
1977  ad = TypedData_Make_Struct(0, struct autoload_data_i,
1978  &autoload_data_i_type, ele);
1979  ele->feature = file;
1980  ele->state = 0;
1981  list_head_init(&ele->constants);
1982  rb_hash_aset(autoload_featuremap, file, ad);
1983  }
1984  else {
1985  ele = rb_check_typeddata(ad, &autoload_data_i_type);
1986  }
1987  {
1988  VALUE acv;
1989  struct autoload_const *ac;
1990  acv = TypedData_Make_Struct(0, struct autoload_const,
1991  &autoload_const_type, ac);
1992  ac->mod = mod;
1993  ac->id = id;
1994  ac->value = Qundef;
1995  ac->flag = CONST_PUBLIC;
1996  ac->ad = ad;
1997  list_add_tail(&ele->constants, &ac->cnode);
1998  st_insert(tbl, (st_data_t)id, (st_data_t)acv);
1999  }
2000 }
2001 
2002 static void
2003 autoload_delete(VALUE mod, ID id)
2004 {
2005  st_data_t val, load = 0, n = id;
2006 
2007  if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
2008  struct st_table *tbl = check_autoload_table((VALUE)val);
2009  struct autoload_data_i *ele;
2010  struct autoload_const *ac;
2011 
2012  st_delete(tbl, &n, &load);
2013  ele = get_autoload_data((VALUE)load, &ac);
2014  VM_ASSERT(ele);
2015  if (ele) {
2016  VM_ASSERT(!list_empty(&ele->constants));
2017  }
2018 
2019  /*
2020  * we must delete here to avoid "already initialized" warnings
2021  * with parallel autoload. Using list_del_init here so list_del
2022  * works in autoload_c_free
2023  */
2024  list_del_init(&ac->cnode);
2025 
2026  if (tbl->num_entries == 0) {
2027  n = autoload;
2028  st_delete(RCLASS_IV_TBL(mod), &n, &val);
2029  }
2030  }
2031 }
2032 
2033 static VALUE
2034 check_autoload_required(VALUE mod, ID id, const char **loadingpath)
2035 {
2036  VALUE file;
2037  VALUE load = autoload_data(mod, id);
2038  struct autoload_data_i *ele;
2039  const char *loading;
2040 
2041  if (!load || !(ele = get_autoload_data(load, 0))) {
2042  return 0;
2043  }
2044  file = ele->feature;
2045  Check_Type(file, T_STRING);
2046  if (!RSTRING_LEN(file) || !*RSTRING_PTR(file)) {
2047  rb_raise(rb_eArgError, "empty file name");
2048  }
2049 
2050  /*
2051  * if somebody else is autoloading, we MUST wait for them, since
2052  * rb_provide_feature can provide a feature before autoload_const_set
2053  * completes. We must wait until autoload_const_set finishes in
2054  * the other thread.
2055  */
2056  if (ele->state && ele->state->thread != rb_thread_current()) {
2057  return load;
2058  }
2059 
2060  loading = RSTRING_PTR(file);
2061  if (!rb_feature_provided(loading, &loading)) {
2062  return load;
2063  }
2064  if (loadingpath && loading) {
2065  *loadingpath = loading;
2066  return load;
2067  }
2068  return 0;
2069 }
2070 
2071 static struct autoload_const *autoloading_const_entry(VALUE mod, ID id);
2072 
2075 {
2076  struct autoload_const *ac = autoloading_const_entry(mod, id);
2077  if (!ac) return FALSE;
2078 
2079  if (value) {
2080  *value = ac->value;
2081  }
2082  if (flag) {
2083  *flag = ac->flag;
2084  }
2085  return TRUE;
2086 }
2087 
2088 struct autoload_const *
2089 autoloading_const_entry(VALUE mod, ID id)
2090 {
2091  VALUE load = autoload_data(mod, id);
2092  struct autoload_data_i *ele;
2093  struct autoload_const *ac;
2094 
2095  if (!load || !(ele = get_autoload_data(load, &ac))) {
2096  return 0;
2097  }
2098 
2099  if (ele->state && ele->state->thread == rb_thread_current()) {
2100  if (ac->value != Qundef) {
2101  return ac;
2102  }
2103  }
2104  return 0;
2105 }
2106 
2107 static int
2108 autoload_defined_p(VALUE mod, ID id)
2109 {
2111 
2112  if (!ce || ce->value != Qundef) {
2113  return 0;
2114  }
2115  return !rb_autoloading_value(mod, id, NULL, NULL);
2116 }
2117 
2118 static void const_tbl_update(struct autoload_const *);
2119 
2120 static VALUE
2121 autoload_const_set(VALUE arg)
2122 {
2123  struct autoload_const *ac = (struct autoload_const *)arg;
2124  VALUE klass = ac->mod;
2125  ID id = ac->id;
2126  check_before_mod_set(klass, id, ac->value, "constant");
2127  const_tbl_update(ac);
2128  return 0; /* ignored */
2129 }
2130 
2131 static VALUE
2132 autoload_require(VALUE arg)
2133 {
2134  struct autoload_state *state = (struct autoload_state *)arg;
2135  struct autoload_const *ac = state->ac;
2136  struct autoload_data_i *ele;
2137 
2138  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2139  /* this may release GVL and switch threads: */
2140  state->result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1,
2141  ele->feature);
2142 
2143  return state->result;
2144 }
2145 
2146 static VALUE
2147 autoload_reset(VALUE arg)
2148 {
2149  struct autoload_state *state = (struct autoload_state *)arg;
2150  int need_wakeups = 0;
2151  struct autoload_const *ac = state->ac;
2152  struct autoload_data_i *ele;
2153 
2154  ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2155  if (ele->state == state) {
2156  need_wakeups = 1;
2157  ele->state = 0;
2158  ele->fork_gen = 0;
2159  }
2160 
2161  /* At the last, move a value defined in autoload to constant table */
2162  if (RTEST(state->result)) {
2163  struct autoload_const *next;
2164 
2165  list_for_each_safe(&ele->constants, ac, next, cnode) {
2166  if (ac->value != Qundef) {
2167  autoload_const_set((VALUE)ac);
2168  }
2169  }
2170  }
2171 
2172  /* wakeup any waiters we had */
2173  if (need_wakeups) {
2174  struct autoload_state *cur = 0, *nxt;
2175 
2176  list_for_each_safe((struct list_head *)&state->waitq, cur, nxt, waitq) {
2177  VALUE th = cur->thread;
2178 
2179  cur->thread = Qfalse;
2180  list_del_init(&cur->waitq); /* idempotent */
2181 
2182  /*
2183  * cur is stored on the stack of cur->waiting_th,
2184  * do not touch cur after waking up waiting_th
2185  */
2187  }
2188  }
2189 
2190  return 0; /* ignored */
2191 }
2192 
2193 static VALUE
2194 autoload_sleep(VALUE arg)
2195 {
2196  struct autoload_state *state = (struct autoload_state *)arg;
2197 
2198  /*
2199  * autoload_reset in other thread will resume us and remove us
2200  * from the waitq list
2201  */
2202  do {
2204  } while (state->thread != Qfalse);
2205 
2206  return Qfalse;
2207 }
2208 
2209 static VALUE
2210 autoload_sleep_done(VALUE arg)
2211 {
2212  struct autoload_state *state = (struct autoload_state *)arg;
2213 
2214  if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) {
2215  list_del(&state->waitq); /* idempotent after list_del_init */
2216  }
2217 
2218  return Qfalse;
2219 }
2220 
2221 VALUE
2223 {
2224  VALUE load, result;
2225  const char *loading = 0, *src;
2226  struct autoload_data_i *ele;
2227  struct autoload_const *ac;
2228  struct autoload_state state;
2229  int flag = -1;
2230  rb_const_entry_t *ce;
2231 
2232  if (!autoload_defined_p(mod, id)) return Qfalse;
2233  load = check_autoload_required(mod, id, &loading);
2234  if (!load) return Qfalse;
2235  src = rb_sourcefile();
2236  if (src && loading && strcmp(src, loading) == 0) return Qfalse;
2237 
2238  if ((ce = rb_const_lookup(mod, id))) {
2239  flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
2240  }
2241 
2242  /* set ele->state for a marker of autoloading thread */
2243  if (!(ele = get_autoload_data(load, &ac))) {
2244  return Qfalse;
2245  }
2246  state.ac = ac;
2247  state.thread = rb_thread_current();
2248  if (!ele->state) {
2249  ele->state = &state;
2250  ele->fork_gen = GET_VM()->fork_gen;
2251 
2252  /*
2253  * autoload_reset will wake up any threads added to this
2254  * iff the GVL is released during autoload_require
2255  */
2256  list_head_init((struct list_head *)&state.waitq);
2257  }
2258  else if (state.thread == ele->state->thread) {
2259  return Qfalse;
2260  }
2261  else {
2262  list_add_tail((struct list_head *)&ele->state->waitq, &state.waitq);
2263 
2264  rb_ensure(autoload_sleep, (VALUE)&state,
2265  autoload_sleep_done, (VALUE)&state);
2266  }
2267 
2268  /* autoload_data_i can be deleted by another thread while require */
2269  state.result = Qfalse;
2270  result = rb_ensure(autoload_require, (VALUE)&state,
2271  autoload_reset, (VALUE)&state);
2272 
2273  if (flag > 0 && (ce = rb_const_lookup(mod, id))) {
2274  ce->flag |= flag;
2275  }
2276  RB_GC_GUARD(load);
2277  return result;
2278 }
2279 
2280 VALUE
2282 {
2283  return rb_autoload_at_p(mod, id, TRUE);
2284 }
2285 
2286 VALUE
2288 {
2289  VALUE load;
2290  struct autoload_data_i *ele;
2291 
2292  while (!autoload_defined_p(mod, id)) {
2293  if (!recur) return Qnil;
2294  mod = RCLASS_SUPER(mod);
2295  if (!mod) return Qnil;
2296  }
2297  load = check_autoload_required(mod, id, 0);
2298  if (!load) return Qnil;
2299  return (ele = get_autoload_data(load, 0)) ? ele->feature : Qnil;
2300 }
2301 
2302 MJIT_FUNC_EXPORTED void
2304 {
2305  if (RB_CONST_DEPRECATED_P(ce) &&
2307  if (klass == rb_cObject) {
2308  rb_warn("constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
2309  }
2310  else {
2311  rb_warn("constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
2312  rb_class_name(klass), QUOTE_ID(id));
2313  }
2314  }
2315 }
2316 
2317 static VALUE
2318 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2319 {
2320  VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
2321  if (c != Qundef) return c;
2322  return rb_const_missing(klass, ID2SYM(id));
2323 }
2324 
2325 static VALUE
2326 rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2327 {
2328  VALUE value, tmp;
2329 
2330  tmp = klass;
2331  while (RTEST(tmp)) {
2332  VALUE am = 0;
2333  rb_const_entry_t *ce;
2334 
2335  while ((ce = rb_const_lookup(tmp, id))) {
2336  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2337  if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass;
2338  GET_EC()->private_const_reference = tmp;
2339  return Qundef;
2340  }
2341  rb_const_warn_if_deprecated(ce, tmp, id);
2342  value = ce->value;
2343  if (value == Qundef) {
2344  struct autoload_const *ac;
2345  if (am == tmp) break;
2346  am = tmp;
2347  ac = autoloading_const_entry(tmp, id);
2348  if (ac) return ac->value;
2349  rb_autoload_load(tmp, id);
2350  continue;
2351  }
2352  if (exclude && tmp == rb_cObject) {
2353  goto not_found;
2354  }
2355  return value;
2356  }
2357  if (!recurse) break;
2358  tmp = RCLASS_SUPER(tmp);
2359  }
2360 
2361  not_found:
2362  GET_EC()->private_const_reference = 0;
2363  return Qundef;
2364 }
2365 
2366 static VALUE
2367 rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
2368 {
2369  VALUE value;
2370 
2371  if (klass == rb_cObject) exclude = FALSE;
2372  value = rb_const_search_from(klass, id, exclude, recurse, visibility);
2373  if (value != Qundef) return value;
2374  if (exclude) return value;
2375  if (BUILTIN_TYPE(klass) != T_MODULE) return value;
2376  /* search global const too, if klass is a module */
2377  return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
2378 }
2379 
2380 VALUE
2382 {
2383  return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
2384 }
2385 
2386 VALUE
2388 {
2389  return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
2390 }
2391 
2392 VALUE
2394 {
2395  return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
2396 }
2397 
2400 {
2401  return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
2402 }
2403 
2406 {
2407  return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
2408 }
2409 
2410 NORETURN(static void undefined_constant(VALUE mod, VALUE name));
2411 static void
2412 undefined_constant(VALUE mod, VALUE name)
2413 {
2414  rb_name_err_raise("constant %2$s::%1$s not defined",
2415  mod, name);
2416 }
2417 
2418 static VALUE
2419 rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2420 {
2421  while (RTEST(klass)) {
2422  rb_const_entry_t *ce;
2423 
2424  while ((ce = rb_const_lookup(klass, id))) {
2425  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2426  return Qnil;
2427  }
2428  if (exclude && klass == rb_cObject) {
2429  goto not_found;
2430  }
2431  if (NIL_P(ce->file)) return rb_ary_new();
2432  return rb_assoc_new(ce->file, INT2NUM(ce->line));
2433  }
2434  if (!recurse) break;
2436  }
2437 
2438  not_found:
2439  return Qnil;
2440 }
2441 
2442 static VALUE
2443 rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility)
2444 {
2445  VALUE loc;
2446 
2447  if (klass == rb_cObject) exclude = FALSE;
2448  loc = rb_const_location_from(klass, id, exclude, recurse, visibility);
2449  if (!NIL_P(loc)) return loc;
2450  if (exclude) return loc;
2451  if (BUILTIN_TYPE(klass) != T_MODULE) return loc;
2452  /* search global const too, if klass is a module */
2453  return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility);
2454 }
2455 
2456 VALUE
2458 {
2459  return rb_const_location(klass, id, FALSE, TRUE, FALSE);
2460 }
2461 
2464 {
2465  return rb_const_location(klass, id, TRUE, FALSE, FALSE);
2466 }
2467 
2468 /*
2469  * call-seq:
2470  * remove_const(sym) -> obj
2471  *
2472  * Removes the definition of the given constant, returning that
2473  * constant's previous value. If that constant referred to
2474  * a module, this will not change that module's name and can lead
2475  * to confusion.
2476  */
2477 
2478 VALUE
2480 {
2481  const ID id = id_for_var(mod, name, a, constant);
2482 
2483  if (!id) {
2484  undefined_constant(mod, name);
2485  }
2486  return rb_const_remove(mod, id);
2487 }
2488 
2489 VALUE
2491 {
2492  VALUE val;
2493  rb_const_entry_t *ce;
2494 
2496  ce = rb_const_lookup(mod, id);
2497  if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2498  if (rb_const_defined_at(mod, id)) {
2499  rb_name_err_raise("cannot remove %2$s::%1$s",
2500  mod, ID2SYM(id));
2501  }
2502  undefined_constant(mod, ID2SYM(id));
2503  }
2504 
2506 
2507  val = ce->value;
2508  if (val == Qundef) {
2509  autoload_delete(mod, id);
2510  val = Qnil;
2511  }
2512  xfree(ce);
2513  return val;
2514 }
2515 
2516 static int
2517 cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
2518 {
2519  if (existing) return ST_STOP;
2520  *v = a;
2521  return ST_CONTINUE;
2522 }
2523 
2524 static enum rb_id_table_iterator_result
2525 sv_i(ID key, VALUE v, void *a)
2526 {
2528  st_table *tbl = a;
2529 
2530  if (rb_is_const_id(key)) {
2531  st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2532  }
2533  return ID_TABLE_CONTINUE;
2534 }
2535 
2536 static enum rb_id_table_iterator_result
2537 rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
2538 {
2539  if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
2540  rb_ary_push((VALUE)ary, ID2SYM(const_name));
2541  }
2542  return ID_TABLE_CONTINUE;
2543 }
2544 
2545 static VALUE
2546 rb_local_constants(VALUE mod)
2547 {
2548  struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
2549  VALUE ary;
2550 
2551  if (!tbl) return rb_ary_new2(0);
2552 
2553  ary = rb_ary_new2(rb_id_table_size(tbl));
2554  rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
2555  return ary;
2556 }
2557 
2558 void*
2560 {
2561  st_table *tbl = data;
2562  if (!tbl) {
2563  tbl = st_init_numtable();
2564  }
2565  if (RCLASS_CONST_TBL(mod)) {
2567  }
2568  return tbl;
2569 }
2570 
2571 void*
2573 {
2574  VALUE tmp = mod;
2575  for (;;) {
2576  data = rb_mod_const_at(tmp, data);
2577  tmp = RCLASS_SUPER(tmp);
2578  if (!tmp) break;
2579  if (tmp == rb_cObject && mod != rb_cObject) break;
2580  }
2581  return data;
2582 }
2583 
2584 static int
2585 list_i(st_data_t key, st_data_t value, VALUE ary)
2586 {
2587  ID sym = (ID)key;
2588  rb_const_entry_t *ce = (rb_const_entry_t *)value;
2589  if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
2590  return ST_CONTINUE;
2591 }
2592 
2593 VALUE
2594 rb_const_list(void *data)
2595 {
2596  st_table *tbl = data;
2597  VALUE ary;
2598 
2599  if (!tbl) return rb_ary_new2(0);
2600  ary = rb_ary_new2(tbl->num_entries);
2601  st_foreach_safe(tbl, list_i, ary);
2602  st_free_table(tbl);
2603 
2604  return ary;
2605 }
2606 
2607 /*
2608  * call-seq:
2609  * mod.constants(inherit=true) -> array
2610  *
2611  * Returns an array of the names of the constants accessible in
2612  * <i>mod</i>. This includes the names of constants in any included
2613  * modules (example at start of section), unless the <i>inherit</i>
2614  * parameter is set to <code>false</code>.
2615  *
2616  * The implementation makes no guarantees about the order in which the
2617  * constants are yielded.
2618  *
2619  * IO.constants.include?(:SYNC) #=> true
2620  * IO.constants(false).include?(:SYNC) #=> false
2621  *
2622  * Also see Module#const_defined?.
2623  */
2624 
2625 VALUE
2627 {
2628  bool inherit = true;
2629 
2630  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
2631 
2632  if (inherit) {
2633  return rb_const_list(rb_mod_const_of(mod, 0));
2634  }
2635  else {
2636  return rb_local_constants(mod);
2637  }
2638 }
2639 
2640 static int
2641 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2642 {
2643  VALUE tmp;
2644  int mod_retry = 0;
2645  rb_const_entry_t *ce;
2646 
2647  tmp = klass;
2648  retry:
2649  while (tmp) {
2650  if ((ce = rb_const_lookup(tmp, id))) {
2651  if (visibility && RB_CONST_PRIVATE_P(ce)) {
2652  return (int)Qfalse;
2653  }
2654  if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
2655  !rb_autoloading_value(tmp, id, NULL, NULL))
2656  return (int)Qfalse;
2657 
2658  if (exclude && tmp == rb_cObject && klass != rb_cObject) {
2659  return (int)Qfalse;
2660  }
2661 
2662  return (int)Qtrue;
2663  }
2664  if (!recurse) break;
2665  tmp = RCLASS_SUPER(tmp);
2666  }
2667  if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
2668  mod_retry = 1;
2669  tmp = rb_cObject;
2670  goto retry;
2671  }
2672  return (int)Qfalse;
2673 }
2674 
2675 int
2677 {
2678  return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
2679 }
2680 
2681 int
2683 {
2684  return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
2685 }
2686 
2687 int
2689 {
2690  return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
2691 }
2692 
2695 {
2696  return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
2697 }
2698 
2699 static void
2700 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
2701 {
2703 }
2704 
2705 static void set_namespace_path(VALUE named_namespace, VALUE name);
2706 
2707 static enum rb_id_table_iterator_result
2708 set_namespace_path_i(ID id, VALUE v, void *payload)
2709 {
2711  VALUE value = ce->value;
2712  int has_permanent_classpath;
2713  VALUE parental_path = *((VALUE *) payload);
2714  if (!rb_is_const_id(id)) {
2715  return ID_TABLE_CONTINUE;
2716  }
2717  if (!rb_namespace_p(value)) {
2718  return ID_TABLE_CONTINUE;
2719  }
2720  classname(value, &has_permanent_classpath);
2721  if (has_permanent_classpath) {
2722  return ID_TABLE_CONTINUE;
2723  }
2724  set_namespace_path(value, build_const_path(parental_path, id));
2725  if (RCLASS_IV_TBL(value)) {
2726  st_data_t tmp = tmp_classpath;
2727  st_delete(RCLASS_IV_TBL(value), &tmp, 0);
2728  }
2729 
2730  return ID_TABLE_CONTINUE;
2731 }
2732 
2733 /*
2734  * Assign permanent classpaths to all namespaces that are directly or indirectly
2735  * nested under +named_namespace+. +named_namespace+ must have a permanent
2736  * classpath.
2737  */
2738 static void
2739 set_namespace_path(VALUE named_namespace, VALUE namespace_path)
2740 {
2741  struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
2742  if (!RCLASS_IV_TBL(named_namespace)) {
2743  RCLASS_IV_TBL(named_namespace) = st_init_numtable();
2744  }
2745  rb_class_ivar_set(named_namespace, classpath, namespace_path);
2746  if (const_table) {
2747  rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
2748  }
2749 }
2750 
2751 void
2753 {
2754  rb_const_entry_t *ce;
2755  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2756 
2757  if (NIL_P(klass)) {
2758  rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
2759  QUOTE_ID(id));
2760  }
2761 
2762  check_before_mod_set(klass, id, val, "constant");
2763  if (!tbl) {
2766  ce = ZALLOC(rb_const_entry_t);
2767  rb_id_table_insert(tbl, id, (VALUE)ce);
2768  setup_const_entry(ce, klass, val, CONST_PUBLIC);
2769  }
2770  else {
2771  struct autoload_const ac;
2772  ac.mod = klass;
2773  ac.id = id;
2774  ac.value = val;
2775  ac.flag = CONST_PUBLIC;
2776  const_tbl_update(&ac);
2777  }
2778  /*
2779  * Resolve and cache class name immediately to resolve ambiguity
2780  * and avoid order-dependency on const_tbl
2781  */
2782  if (rb_cObject && rb_namespace_p(val)) {
2783  int val_path_permanent;
2784  VALUE val_path = classname(val, &val_path_permanent);
2785  if (NIL_P(val_path) || !val_path_permanent) {
2786  if (klass == rb_cObject) {
2787  set_namespace_path(val, rb_id2str(id));
2788  }
2789  else {
2790  int parental_path_permanent;
2791  VALUE parental_path = classname(klass, &parental_path_permanent);
2792  if (!NIL_P(parental_path)) {
2793  if (parental_path_permanent && !val_path_permanent) {
2794  set_namespace_path(val, build_const_path(parental_path, id));
2795  }
2796  else if (!parental_path_permanent && NIL_P(val_path)) {
2797  rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
2798  }
2799  }
2800  }
2801  }
2802  }
2803 }
2804 
2805 static struct autoload_data_i *
2806 current_autoload_data(VALUE mod, ID id, struct autoload_const **acp)
2807 {
2808  struct autoload_data_i *ele;
2809  VALUE load = autoload_data(mod, id);
2810  if (!load) return 0;
2811  ele = get_autoload_data(load, acp);
2812  if (!ele) return 0;
2813  /* for autoloading thread, keep the defined value to autoloading storage */
2814  if (ele->state && (ele->state->thread == rb_thread_current())) {
2815  return ele;
2816  }
2817  return 0;
2818 }
2819 
2820 static void
2821 const_tbl_update(struct autoload_const *ac)
2822 {
2823  VALUE value;
2824  VALUE klass = ac->mod;
2825  VALUE val = ac->value;
2826  ID id = ac->id;
2827  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2828  rb_const_flag_t visibility = ac->flag;
2829  rb_const_entry_t *ce;
2830 
2831  if (rb_id_table_lookup(tbl, id, &value)) {
2832  ce = (rb_const_entry_t *)value;
2833  if (ce->value == Qundef) {
2834  struct autoload_data_i *ele = current_autoload_data(klass, id, &ac);
2835 
2836  if (ele) {
2838 
2839  ac->value = val; /* autoload_i is non-WB-protected */
2840  return;
2841  }
2842  /* otherwise, allow to override */
2843  autoload_delete(klass, id);
2844  }
2845  else {
2846  VALUE name = QUOTE_ID(id);
2847  visibility = ce->flag;
2848  if (klass == rb_cObject)
2849  rb_warn("already initialized constant %"PRIsVALUE"", name);
2850  else
2851  rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
2853  if (!NIL_P(ce->file) && ce->line) {
2855  "previous definition of %"PRIsVALUE" was here", name);
2856  }
2857  }
2859  setup_const_entry(ce, klass, val, visibility);
2860  }
2861  else {
2863 
2864  ce = ZALLOC(rb_const_entry_t);
2865  rb_id_table_insert(tbl, id, (VALUE)ce);
2866  setup_const_entry(ce, klass, val, visibility);
2867  }
2868 }
2869 
2870 static void
2871 setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
2872  rb_const_flag_t visibility)
2873 {
2874  ce->flag = visibility;
2875  RB_OBJ_WRITE(klass, &ce->value, val);
2877 }
2878 
2879 void
2881 {
2882  ID id = rb_intern(name);
2883 
2884  if (!rb_is_const_id(id)) {
2885  rb_warn("rb_define_const: invalid name `%s' for constant", name);
2886  }
2888  rb_const_set(klass, id, val);
2889 }
2890 
2891 void
2893 {
2895 }
2896 
2897 static void
2898 set_const_visibility(VALUE mod, int argc, const VALUE *argv,
2900 {
2901  int i;
2902  rb_const_entry_t *ce;
2903  ID id;
2904 
2906  if (argc == 0) {
2907  rb_warning("%"PRIsVALUE" with no argument is just ignored",
2909  return;
2910  }
2911 
2912  for (i = 0; i < argc; i++) {
2913  struct autoload_const *ac;
2914  VALUE val = argv[i];
2915  id = rb_check_id(&val);
2916  if (!id) {
2917  if (i > 0) {
2919  }
2920 
2921  undefined_constant(mod, val);
2922  }
2923  if ((ce = rb_const_lookup(mod, id))) {
2924  ce->flag &= ~mask;
2925  ce->flag |= flag;
2926  if (ce->value == Qundef) {
2927  struct autoload_data_i *ele;
2928 
2929  ele = current_autoload_data(mod, id, &ac);
2930  if (ele) {
2931  ac->flag &= ~mask;
2932  ac->flag |= flag;
2933  }
2934  }
2935  }
2936  else {
2937  if (i > 0) {
2939  }
2940  undefined_constant(mod, ID2SYM(id));
2941  }
2942  }
2944 }
2945 
2946 void
2948 {
2949  rb_const_entry_t *ce;
2950  ID id;
2951  long len = strlen(name);
2952 
2954  if (!(id = rb_check_id_cstr(name, len, NULL))) {
2955  undefined_constant(mod, rb_fstring_new(name, len));
2956  }
2957  if (!(ce = rb_const_lookup(mod, id))) {
2958  undefined_constant(mod, ID2SYM(id));
2959  }
2960  ce->flag |= CONST_DEPRECATED;
2961 }
2962 
2963 /*
2964  * call-seq:
2965  * mod.private_constant(symbol, ...) => mod
2966  *
2967  * Makes a list of existing constants private.
2968  */
2969 
2970 VALUE
2972 {
2973  set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
2974  return obj;
2975 }
2976 
2977 /*
2978  * call-seq:
2979  * mod.public_constant(symbol, ...) => mod
2980  *
2981  * Makes a list of existing constants public.
2982  */
2983 
2984 VALUE
2986 {
2987  set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
2988  return obj;
2989 }
2990 
2991 /*
2992  * call-seq:
2993  * mod.deprecate_constant(symbol, ...) => mod
2994  *
2995  * Makes a list of existing constants deprecated. Attempt
2996  * to refer to them will produce a warning.
2997  *
2998  * module HTTP
2999  * NotFound = Exception.new
3000  * NOT_FOUND = NotFound # previous version of the library used this name
3001  *
3002  * deprecate_constant :NOT_FOUND
3003  * end
3004  *
3005  * HTTP::NOT_FOUND
3006  * # warning: constant HTTP::NOT_FOUND is deprecated
3007  *
3008  */
3009 
3010 VALUE
3012 {
3013  set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3014  return obj;
3015 }
3016 
3017 static VALUE
3018 original_module(VALUE c)
3019 {
3020  if (RB_TYPE_P(c, T_ICLASS))
3021  return RBASIC(c)->klass;
3022  return c;
3023 }
3024 
3025 static int
3026 cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3027 {
3028  if (!RCLASS_IV_TBL(klass)) return 0;
3029  return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v);
3030 }
3031 
3032 static VALUE
3033 cvar_front_klass(VALUE klass)
3034 {
3035  if (FL_TEST(klass, FL_SINGLETON)) {
3037  if (rb_namespace_p(obj)) {
3038  return obj;
3039  }
3040  }
3041  return RCLASS_SUPER(klass);
3042 }
3043 
3044 static void
3045 cvar_overtaken(VALUE front, VALUE target, ID id)
3046 {
3047  if (front && target != front) {
3048  st_data_t did = (st_data_t)id;
3049 
3050  if (RTEST(ruby_verbose) && original_module(front) != original_module(target)) {
3051  rb_warning("class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3052  ID2SYM(id), rb_class_name(original_module(front)),
3053  rb_class_name(original_module(target)));
3054  }
3055  if (BUILTIN_TYPE(front) == T_CLASS) {
3056  st_delete(RCLASS_IV_TBL(front), &did, 0);
3057  }
3058  }
3059 }
3060 
3061 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3062  for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3063  if (cvar_lookup_at(klass, id, (v))) { \
3064  r; \
3065  } \
3066  }
3067 
3068 #define CVAR_LOOKUP(v,r) do {\
3069  if (cvar_lookup_at(klass, id, (v))) {r;}\
3070  CVAR_FOREACH_ANCESTORS(klass, v, r);\
3071 } while(0)
3072 
3073 void
3075 {
3076  VALUE tmp, front = 0, target = 0;
3077 
3078  tmp = klass;
3079  CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3080  if (target) {
3081  cvar_overtaken(front, target, id);
3082  }
3083  else {
3084  target = tmp;
3085  }
3086 
3087  check_before_mod_set(target, id, val, "class variable");
3088  if (!RCLASS_IV_TBL(target)) {
3089  RCLASS_IV_TBL(target) = st_init_numtable();
3090  }
3091 
3092  rb_class_ivar_set(target, id, val);
3093 }
3094 
3095 VALUE
3097 {
3098  VALUE tmp, front = 0, target = 0;
3099  st_data_t value;
3100 
3101  tmp = klass;
3102  CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
3103  if (!target) {
3104  rb_name_err_raise("uninitialized class variable %1$s in %2$s",
3105  tmp, ID2SYM(id));
3106  }
3107  cvar_overtaken(front, target, id);
3108  return (VALUE)value;
3109 }
3110 
3111 VALUE
3113 {
3114  if (!klass) return Qfalse;
3115  CVAR_LOOKUP(0,return Qtrue);
3116  return Qfalse;
3117 }
3118 
3119 static ID
3120 cv_intern(VALUE klass, const char *name)
3121 {
3122  ID id = rb_intern(name);
3123  if (!rb_is_class_id(id)) {
3124  rb_name_err_raise("wrong class variable name %1$s",
3126  }
3127  return id;
3128 }
3129 
3130 void
3131 rb_cv_set(VALUE klass, const char *name, VALUE val)
3132 {
3133  ID id = cv_intern(klass, name);
3134  rb_cvar_set(klass, id, val);
3135 }
3136 
3137 VALUE
3138 rb_cv_get(VALUE klass, const char *name)
3139 {
3140  ID id = cv_intern(klass, name);
3141  return rb_cvar_get(klass, id);
3142 }
3143 
3144 void
3146 {
3147  ID id = cv_intern(klass, name);
3148  rb_cvar_set(klass, id, val);
3149 }
3150 
3151 static int
3152 cv_i(st_data_t k, st_data_t v, st_data_t a)
3153 {
3154  ID key = (ID)k;
3155  st_table *tbl = (st_table *)a;
3156 
3157  if (rb_is_class_id(key)) {
3158  st_update(tbl, (st_data_t)key, cv_i_update, 0);
3159  }
3160  return ST_CONTINUE;
3161 }
3162 
3163 static void*
3164 mod_cvar_at(VALUE mod, void *data)
3165 {
3166  st_table *tbl = data;
3167  if (!tbl) {
3168  tbl = st_init_numtable();
3169  }
3170  if (RCLASS_IV_TBL(mod)) {
3172  }
3173  return tbl;
3174 }
3175 
3176 static void*
3177 mod_cvar_of(VALUE mod, void *data)
3178 {
3179  VALUE tmp = mod;
3180  if (FL_TEST(mod, FL_SINGLETON)) {
3181  if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) {
3182  data = mod_cvar_at(tmp, data);
3183  tmp = cvar_front_klass(tmp);
3184  }
3185  }
3186  for (;;) {
3187  data = mod_cvar_at(tmp, data);
3188  tmp = RCLASS_SUPER(tmp);
3189  if (!tmp) break;
3190  }
3191  return data;
3192 }
3193 
3194 static int
3195 cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3196 {
3197  ID sym = (ID)key;
3198  rb_ary_push(ary, ID2SYM(sym));
3199  return ST_CONTINUE;
3200 }
3201 
3202 static VALUE
3203 cvar_list(void *data)
3204 {
3205  st_table *tbl = data;
3206  VALUE ary;
3207 
3208  if (!tbl) return rb_ary_new2(0);
3209  ary = rb_ary_new2(tbl->num_entries);
3210  st_foreach_safe(tbl, cv_list_i, ary);
3211  st_free_table(tbl);
3212 
3213  return ary;
3214 }
3215 
3216 /*
3217  * call-seq:
3218  * mod.class_variables(inherit=true) -> array
3219  *
3220  * Returns an array of the names of class variables in <i>mod</i>.
3221  * This includes the names of class variables in any included
3222  * modules, unless the <i>inherit</i> parameter is set to
3223  * <code>false</code>.
3224  *
3225  * class One
3226  * @@var1 = 1
3227  * end
3228  * class Two < One
3229  * @@var2 = 2
3230  * end
3231  * One.class_variables #=> [:@@var1]
3232  * Two.class_variables #=> [:@@var2, :@@var1]
3233  * Two.class_variables(false) #=> [:@@var2]
3234  */
3235 
3236 VALUE
3238 {
3239  bool inherit = true;
3240  st_table *tbl;
3241 
3242  if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3243  if (inherit) {
3244  tbl = mod_cvar_of(mod, 0);
3245  }
3246  else {
3247  tbl = mod_cvar_at(mod, 0);
3248  }
3249  return cvar_list(tbl);
3250 }
3251 
3252 /*
3253  * call-seq:
3254  * remove_class_variable(sym) -> obj
3255  *
3256  * Removes the definition of the <i>sym</i>, returning that
3257  * constant's value.
3258  *
3259  * class Dummy
3260  * @@var = 99
3261  * puts @@var
3262  * remove_class_variable(:@@var)
3263  * p(defined? @@var)
3264  * end
3265  *
3266  * <em>produces:</em>
3267  *
3268  * 99
3269  * nil
3270  */
3271 
3272 VALUE
3274 {
3275  const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
3276  st_data_t val, n = id;
3277 
3278  if (!id) {
3279  not_defined:
3280  rb_name_err_raise("class variable %1$s not defined for %2$s",
3281  mod, name);
3282  }
3284  if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
3285  return (VALUE)val;
3286  }
3287  if (rb_cvar_defined(mod, id)) {
3288  rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
3289  }
3290  goto not_defined;
3291 }
3292 
3293 VALUE
3294 rb_iv_get(VALUE obj, const char *name)
3295 {
3297 
3298  if (!id) {
3299  if (RTEST(ruby_verbose))
3300  rb_warning("instance variable %s not initialized", name);
3301  return Qnil;
3302  }
3303  return rb_ivar_get(obj, id);
3304 }
3305 
3306 VALUE
3307 rb_iv_set(VALUE obj, const char *name, VALUE val)
3308 {
3309  ID id = rb_intern(name);
3310 
3311  return rb_ivar_set(obj, id, val);
3312 }
3313 
3314 /* tbl = xx(obj); tbl[key] = value; */
3315 int
3317 {
3318  st_table *tbl = RCLASS_IV_TBL(obj);
3319  int result = st_insert(tbl, (st_data_t)key, (st_data_t)value);
3320  RB_OBJ_WRITTEN(obj, Qundef, value);
3321  return result;
3322 }
3323 
3324 static int
3325 tbl_copy_i(st_data_t key, st_data_t value, st_data_t data)
3326 {
3327  RB_OBJ_WRITTEN((VALUE)data, Qundef, (VALUE)value);
3328  return ST_CONTINUE;
3329 }
3330 
3331 void
3333 {
3334  st_table *orig_tbl = RCLASS_IV_TBL(src);
3335  st_table *new_tbl = st_copy(orig_tbl);
3336  st_foreach(new_tbl, tbl_copy_i, (st_data_t)dst);
3337  RCLASS_IV_TBL(dst) = new_tbl;
3338 }
3339 
3342 {
3343  struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3344  VALUE val;
3345 
3346  if (tbl && rb_id_table_lookup(tbl, id, &val)) {
3347  return (rb_const_entry_t *)val;
3348  }
3349  return 0;
3350 }
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:1272
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:2572
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:3316
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:3145
rb_const_defined
int rb_const_defined(VALUE klass, ID id)
Definition: variable.c:2682
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
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:3068
rb_mod_const_at
void * rb_mod_const_at(VALUE mod, void *data)
Definition: variable.c:2559
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:2257
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:3096
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:1810
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:437
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:4203
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:7063
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
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:313
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:7983
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:334
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:27
ivar_update::iv_index_tbl
st_table * iv_index_tbl
Definition: variable.c:40
ST_STOP
@ ST_STOP
Definition: st.h:99
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE mod, VALUE name)
Definition: variable.c:2479
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:2463
rb_mark_tbl_no_pin
void rb_mark_tbl_no_pin(st_table *tbl)
Definition: gc.c:5011
rb_warning_category_enabled_p
MJIT_FUNC_EXPORTED bool rb_warning_category_enabled_p(rb_warning_category_t category)
Definition: error.c:164
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
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:1933
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:1817
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
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:3074
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
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
list_del
#define list_del(n)
Definition: rb_mjit_min_header-2.7.0.h:9041
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:1812
rb_gc_mark_global_tbl
void rb_gc_mark_global_tbl(void)
Definition: variable.c:434
int32_t
__int32_t int32_t
Definition: rb_mjit_min_header-2.7.0.h:1175
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:8111
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
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
rb_id_table_iterator_result
rb_id_table_iterator_result
Definition: id_table.h:8
old
VALUE ID VALUE old
Definition: rb_mjit_min_header-2.7.0.h:16133
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
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:1924
rb_define_readonly_variable
void rb_define_readonly_variable(const char *name, const VALUE *var)
Definition: variable.c:505
idConst_missing
@ idConst_missing
Definition: rb_mjit_min_header-2.7.0.h:8691
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:3112
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:2752
rb_eNameError
VALUE rb_eNameError
Definition: error.c:927
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:74
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:1513
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:2457
rb_const_list
VALUE rb_const_list(void *data)
Definition: variable.c:2594
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:2626
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:2074
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
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:1811
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
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
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:28
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
rb_global_variable::data
VALUE * data
Definition: variable.c:304
autoload_data_i::fork_gen
rb_serial_t fork_gen
Definition: variable.c:1820
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
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
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
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_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:7718
rb_global_entry::id
ID id
Definition: internal.h:1352
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
rb_autoload_load
VALUE rb_autoload_load(VALUE mod, ID id)
Definition: variable.c:2222
autoload_state::waitq
struct list_node waitq
Definition: variable.c:1814
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:2287
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:5044
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.0.h:17268
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
rb_encoding
const typedef OnigEncodingType rb_encoding
Definition: encoding.h:115
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:3294
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:2688
list_head
Definition: rb_mjit_min_header-2.7.0.h:8975
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
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
FL_EXIVAR
#define FL_EXIVAR
Definition: ruby.h:1286
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3345
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
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
mask
enum @11::@13::@14 mask
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:3011
rb_set_class_path_string
void rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
Definition: variable.c:198
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.0.h:4052
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
list_add_tail
#define list_add_tail(h, n)
Definition: rb_mjit_min_header-2.7.0.h:9023
gen_ivar_tag::ivtbl
struct gen_ivtbl * ivtbl
Definition: variable.c:1386
trace_var::removed
int removed
Definition: variable.c:295
transient_heap.h
list_empty
#define list_empty(h)
Definition: rb_mjit_min_header-2.7.0.h:9030
list_del_init
#define list_del_init(n)
Definition: rb_mjit_min_header-2.7.0.h:9048
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:922
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
autoload_const::flag
rb_const_flag_t flag
Definition: variable.c:1806
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:920
rb_gvar_is_traced
bool rb_gvar_is_traced(const struct rb_global_entry *entry)
Definition: variable.c:714
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
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:1799
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:5206
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
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_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
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:2405
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:2258
rb_fstring_new
VALUE rb_fstring_new(const char *ptr, long len)
Definition: string.c:396
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
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:1199
QUOTE_ID
#define QUOTE_ID(id)
Definition: internal.h:2143
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.0.h:2836
strcmp
int strcmp(const char *, const char *)
T_MODULE
#define T_MODULE
Definition: ruby.h:526
rb_iv_tbl_copy
void rb_iv_tbl_copy(VALUE dst, VALUE src)
Definition: variable.c:3332
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:2490
char
#define char
Definition: rb_mjit_min_header-2.7.0.h:2876
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:3341
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:2381
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
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:1821
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
ROBJ_TRANSIENT_P
#define ROBJ_TRANSIENT_P(obj)
Definition: internal.h:2256
argv
char ** argv
Definition: ruby.c:223
autoload_const::id
ID id
Definition: variable.c:1805
rb_define_global_const
void rb_define_global_const(const char *name, VALUE val)
Definition: variable.c:2892
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:2281
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
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
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
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
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:2399
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:1819
autoload_state::thread
VALUE thread
Definition: variable.c:1813
obj_ivar_tag::arg
st_data_t arg
Definition: variable.c:1352
fallback_func
VALUE(* fallback_func)(VALUE obj, VALUE name)
Definition: variable.c:127
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:2387
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
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:2947
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:2303
rb_hash_delete
VALUE rb_hash_delete(VALUE hash, VALUE key)
Definition: hash.c:2271
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:1528
list_node
Definition: rb_mjit_min_header-2.7.0.h:8971
rb_define_const
void rb_define_const(VALUE klass, const char *name, VALUE val)
Definition: variable.c:2880
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:3131
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:1572
rb_global_variable
Definition: variable.c:301
xfree
#define xfree
Definition: defines.h:216
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
rb_mod_remove_cvar
VALUE rb_mod_remove_cvar(VALUE mod, VALUE name)
Definition: variable.c:3273
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
autoload_data_i::feature
VALUE feature
Definition: variable.c:1818
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:889
_
#define _(args)
Definition: dln.h:28
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:270
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:2676
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:2142
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:26
rb_class_path
VALUE rb_class_path(VALUE klass)
Definition: variable.c:153
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_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:2971
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
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
rb_mod_class_variables
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
Definition: variable.c:3237
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_public_const_defined_from
MJIT_FUNC_EXPORTED int rb_public_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2694
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:1114
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
RB_WARN_CATEGORY_DEPRECATED
@ RB_WARN_CATEGORY_DEPRECATED
Definition: internal.h:1560
gen_ivtbl
Definition: variable.h:4
ROBJECT_EMBED
@ ROBJECT_EMBED
Definition: ruby.h:917
ivar_update::u
union ivar_update::@169 u
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
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:3138
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:1574
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:24
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:2985
st_free_table
void st_free_table(st_table *tab)
Definition: st.c:709
list_for_each_safe
#define list_for_each_safe(h, i, nxt, member)
Definition: rb_mjit_min_header-2.7.0.h:9097
st_table
Definition: st.h:79
rb_const_get_at
VALUE rb_const_get_at(VALUE klass, ID id)
Definition: variable.c:2393
rb_mod_const_missing
VALUE rb_mod_const_missing(VALUE klass, VALUE name)
Definition: variable.c:1739
id__attached__
@ id__attached__
Definition: rb_mjit_min_header-2.7.0.h:8708
ID_TABLE_CONTINUE
@ ID_TABLE_CONTINUE
Definition: id_table.h:9
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:3307
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
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837