Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
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
28static struct rb_id_table *rb_global_tbl;
29static ID autoload, classpath, tmp_classpath;
30static VALUE autoload_featuremap; /* feature => autoload_i */
31
32static void check_before_mod_set(VALUE, ID, VALUE, const char *);
33static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
34static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
35static st_table *generic_iv_tbl;
36static st_table *generic_iv_tbl_compat;
37
39 union {
42 } u;
45};
46
47void
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
59static inline bool
60rb_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
77static VALUE
78classname(VALUE klass, int *permanent)
79{
80 st_table *ivtbl;
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
101VALUE
103{
104 int permanent;
105 return classname(mod, &permanent);
106}
107
108static VALUE
109make_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 }
124 return path;
125}
126
128
129static VALUE
130rb_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
152VALUE
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
161VALUE
163{
164 int permanent;
165 return classname(klass, &permanent);
166}
167
168static VALUE
169no_fallback(VALUE obj, VALUE name)
170{
171 return name;
172}
173
174VALUE
176{
177 int permanent;
178 return rb_tmp_class_path(klass, &permanent, no_fallback);
179}
180
181static VALUE
182build_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);
188 return path;
189}
190
191static VALUE
192build_const_path(VALUE head, ID tail)
193{
194 return build_const_pathname(head, rb_id2str(tail));
195}
196
197void
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
217void
219{
223}
224
225VALUE
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
267VALUE
268rb_path2class(const char *path)
269{
271}
272
273VALUE
275{
277}
278
279const 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
288const char *
290{
291 return rb_class2name(CLASS_OF(obj));
292}
293
294struct trace_var {
299};
300
309};
310
311static struct rb_global_entry*
312rb_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
348VALUE
350{
351 rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id));
352
353 return Qnil;
354}
355
356void
358{
359 struct rb_global_variable *var = rb_global_entry(id)->var;
363
364 var->data = (void*)val;
365}
366
367void
369{
370}
371
372VALUE
374{
375 return (VALUE)data;
376}
377
378void
380{
381 struct rb_global_variable *var = rb_global_entry(id)->var;
382 var->data = (void*)val;
383}
384
385void
387{
388 VALUE data = (VALUE)var;
390}
391
392VALUE
394{
395 if (!var) return Qnil;
396 return *var;
397}
398
399void
401{
402 *data = val;
403}
404
405void
407{
408 if (var) rb_gc_mark_maybe(*var);
409}
410
411void
413{
414 rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id));
415}
416
418mark_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
433void
435{
436 if (rb_global_tbl)
437 rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
438}
439
440static ID
441global_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
458static ID
459find_global_id(const char *name)
460{
461 ID id;
462 size_t len = strlen(name);
463
464 if (name[0] == '$') {
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
479void
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;
494
495 RB_GC_GUARD(tmp);
496}
497
498void
499rb_define_variable(const char *name, VALUE *var)
500{
502}
503
504void
505rb_define_readonly_variable(const char *name, const VALUE *var)
506{
508}
509
510void
512 const char *name,
515{
519}
520
521static void
522rb_trace_eval(VALUE cmd, VALUE val)
523{
525}
526
527VALUE
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
551static void
552remove_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
573VALUE
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
628};
629
630static VALUE
631trace_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
644static VALUE
645trace_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
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
670VALUE
671rb_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
679VALUE
680rb_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
713bool
715{
716 return !!entry->var->trace;
717}
718
720gvar_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
727VALUE
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
755void
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
790static int
791gen_ivtbl_get(VALUE obj, struct gen_ivtbl **ivtbl)
792{
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
808static VALUE
809generic_ivar_delete(VALUE obj, ID id, VALUE undef)
810{
811 struct gen_ivtbl *ivtbl;
812
813 if (gen_ivtbl_get(obj, &ivtbl)) {
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
829static VALUE
830generic_ivar_get(VALUE obj, ID id, VALUE undef)
831{
832 struct gen_ivtbl *ivtbl;
833
834 if (gen_ivtbl_get(obj, &ivtbl)) {
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
849static size_t
850gen_ivtbl_bytes(size_t n)
851{
852 return offsetof(struct gen_ivtbl, ivptr) + n * sizeof(VALUE);
853}
854
855static struct gen_ivtbl *
856gen_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
870static struct gen_ivtbl *
871gen_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
882static uint32_t
883iv_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
895static int
896generic_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 {
913 ivtbl = 0;
914resize:
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
923static VALUE
924generic_ivar_defined(VALUE obj, ID id)
925{
926 struct gen_ivtbl *ivtbl;
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
940static int
941generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
942{
943 struct gen_ivtbl *ivtbl;
944 st_data_t key = (st_data_t)id;
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
962static void
963gen_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
972void
974{
975 struct gen_ivtbl *ivtbl;
976
977 if (gen_ivtbl_get(obj, &ivtbl)) {
978 gen_ivtbl_mark(ivtbl);
979 }
980}
981
982void
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
992void
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
1009RUBY_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
1019static size_t
1020gen_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
1034VALUE
1036{
1037 VALUE val, *ptr;
1038 struct st_table *iv_index_tbl;
1039 uint32_t len;
1041
1042 if (SPECIAL_CONST_P(obj)) return undef;
1043 switch (BUILTIN_TYPE(obj)) {
1044 case T_OBJECT:
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
1069VALUE
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
1083VALUE
1085{
1086 return rb_ivar_lookup(obj, id, Qnil);
1087}
1088
1089static VALUE
1090rb_ivar_delete(VALUE obj, ID id, VALUE undef)
1091{
1092 VALUE val, *ptr;
1093 struct st_table *iv_index_tbl;
1094 uint32_t len;
1096
1098 switch (BUILTIN_TYPE(obj)) {
1099 case T_OBJECT:
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
1125VALUE
1127{
1128 return rb_ivar_delete(obj, id, Qnil);
1129}
1130
1131static st_table *
1132iv_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
1144static void
1145iv_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
1158static void
1159generic_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
1174static VALUE *
1175obj_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
1189static VALUE *
1190obj_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
1214void
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
1235static VALUE
1236obj_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);
1245 if (len <= ivup.index) {
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
1279static void
1280ivar_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
1299VALUE
1301{
1303 ivar_set(obj, id, val);
1304 return val;
1305}
1306
1307void
1309{
1310 // should be internal instance variable name (no @ prefix)
1312
1313 ivar_set(obj, id, val);
1314}
1315
1316VALUE
1318{
1319 VALUE val;
1320 struct st_table *iv_index_tbl;
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
1355static int
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
1368static void
1370{
1371 st_table *tbl;
1372 struct obj_ivar_tag data;
1373
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
1389};
1390
1391static int
1392gen_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
1405static 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
1424};
1425
1426static int
1427gen_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
1446void
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
1488void
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
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) {
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
1549static int
1550ivar_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
1578VALUE
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))
1594static ID
1595check_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
1633VALUE
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;
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
1681NORETURN(static void uninitialized_constant(VALUE, VALUE));
1682static void
1683uninitialized_constant(VALUE klass, VALUE name)
1684{
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
1693VALUE
1695{
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
1738VALUE
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
1752static void
1753autoload_mark(void *ptr)
1754{
1756}
1757
1758static void
1759autoload_free(void *ptr)
1760{
1762}
1763
1764static size_t
1765autoload_memsize(const void *ptr)
1766{
1767 const st_table *tbl = ptr;
1768 return st_memsize(tbl);
1769}
1770
1771static void
1772autoload_compact(void *ptr)
1773{
1775}
1776
1777static 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
1786static VALUE
1787autoload_data(VALUE mod, ID id)
1788{
1789 struct st_table *tbl;
1790 st_data_t val;
1791
1792 if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
1793 !(tbl = check_autoload_table((VALUE)val)) ||
1794 !st_lookup(tbl, (st_data_t)id, &val)) {
1795 return 0;
1796 }
1797 return (VALUE)val;
1798}
1799
1801 struct list_node cnode; /* <=> autoload_data_i.constants */
1803 VALUE ad; /* autoload_data_i */
1808 int line;
1809};
1810
1811/* always on stack, no need to mark */
1817};
1818
1821 struct autoload_state *state; /* points to on-stack struct */
1823 struct list_head constants; /* <=> autoload_const.cnode */
1824};
1825
1826static void
1827autoload_i_compact(void *ptr)
1828{
1829 struct autoload_data_i *p = ptr;
1831}
1832
1833static void
1834autoload_i_mark(void *ptr)
1835{
1836 struct autoload_data_i *p = ptr;
1837
1839
1840 /* allow GC to free us if no modules refer to this via autoload_const.ad */
1841 if (list_empty(&p->constants)) {
1842 rb_hash_delete(autoload_featuremap, p->feature);
1843 }
1844}
1845
1846static void
1847autoload_i_free(void *ptr)
1848{
1849 struct autoload_data_i *p = ptr;
1850
1851 /* we may leak some memory at VM shutdown time, no big deal */
1852 if (list_empty(&p->constants)) {
1853 xfree(p);
1854 }
1855}
1856
1857static size_t
1858autoload_i_memsize(const void *ptr)
1859{
1860 return sizeof(struct autoload_data_i);
1861}
1862
1863static const rb_data_type_t autoload_data_i_type = {
1864 "autoload_i",
1865 {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact},
1867};
1868
1869static void
1870autoload_c_compact(void *ptr)
1871{
1872 struct autoload_const *ac = ptr;
1873
1874 ac->mod = rb_gc_location(ac->mod);
1875 ac->ad = rb_gc_location(ac->ad);
1876 ac->value = rb_gc_location(ac->value);
1877 ac->file = rb_gc_location(ac->file);
1878}
1879
1880static void
1881autoload_c_mark(void *ptr)
1882{
1883 struct autoload_const *ac = ptr;
1884
1889}
1890
1891static void
1892autoload_c_free(void *ptr)
1893{
1894 struct autoload_const *ac = ptr;
1895 list_del(&ac->cnode);
1896 xfree(ac);
1897}
1898
1899static size_t
1900autoload_c_memsize(const void *ptr)
1901{
1902 return sizeof(struct autoload_const);
1903}
1904
1905static const rb_data_type_t autoload_const_type = {
1906 "autoload_const",
1907 {autoload_c_mark, autoload_c_free, autoload_c_memsize, autoload_c_compact,},
1909};
1910
1911static struct autoload_data_i *
1912get_autoload_data(VALUE acv, struct autoload_const **acp)
1913{
1914 struct autoload_const *ac = rb_check_typeddata(acv, &autoload_const_type);
1915 struct autoload_data_i *ele;
1916
1917 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
1918 /* do not reach across stack for ->state after forking: */
1919 if (ele && ele->state && ele->fork_gen != GET_VM()->fork_gen) {
1920 ele->state = 0;
1921 ele->fork_gen = 0;
1922 }
1923 if (acp) *acp = ac;
1924 return ele;
1925}
1926
1928rb_autoload(VALUE mod, ID id, const char *file)
1929{
1930 if (!file || !*file) {
1931 rb_raise(rb_eArgError, "empty file name");
1932 }
1934}
1935
1936void
1938{
1939 st_data_t av;
1940 VALUE ad;
1941 struct st_table *tbl;
1942 struct autoload_data_i *ele;
1943 rb_const_entry_t *ce;
1944
1945 if (!rb_is_const_id(id)) {
1946 rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"",
1947 QUOTE_ID(id));
1948 }
1949
1950 Check_Type(file, T_STRING);
1951 if (!RSTRING_LEN(file)) {
1952 rb_raise(rb_eArgError, "empty file name");
1953 }
1954
1955 ce = rb_const_lookup(mod, id);
1956 if (ce && ce->value != Qundef) {
1957 return;
1958 }
1959
1960 rb_const_set(mod, id, Qundef);
1961 tbl = RCLASS_IV_TBL(mod);
1962 if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
1963 tbl = check_autoload_table((VALUE)av);
1964 }
1965 else {
1966 if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
1967 av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
1968 st_add_direct(tbl, (st_data_t)autoload, av);
1969 RB_OBJ_WRITTEN(mod, Qnil, av);
1970 DATA_PTR(av) = tbl = st_init_numtable();
1971 }
1972
1973 file = rb_fstring(file);
1974 if (!autoload_featuremap) {
1975 autoload_featuremap = rb_ident_hash_new();
1976 rb_obj_hide(autoload_featuremap);
1977 rb_gc_register_mark_object(autoload_featuremap);
1978 }
1979 ad = rb_hash_aref(autoload_featuremap, file);
1980 if (NIL_P(ad)) {
1982 &autoload_data_i_type, ele);
1983 ele->feature = file;
1984 ele->state = 0;
1985 list_head_init(&ele->constants);
1986 rb_hash_aset(autoload_featuremap, file, ad);
1987 }
1988 else {
1989 ele = rb_check_typeddata(ad, &autoload_data_i_type);
1990 }
1991 {
1992 VALUE acv;
1993 struct autoload_const *ac;
1994 acv = TypedData_Make_Struct(0, struct autoload_const,
1995 &autoload_const_type, ac);
1996 ac->mod = mod;
1997 ac->id = id;
1998 ac->value = Qundef;
1999 ac->flag = CONST_PUBLIC;
2000 ac->ad = ad;
2001 list_add_tail(&ele->constants, &ac->cnode);
2002 st_insert(tbl, (st_data_t)id, (st_data_t)acv);
2003 }
2004}
2005
2006static void
2007autoload_delete(VALUE mod, ID id)
2008{
2009 st_data_t val, load = 0, n = id;
2010
2011 if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
2012 struct st_table *tbl = check_autoload_table((VALUE)val);
2013 struct autoload_data_i *ele;
2014 struct autoload_const *ac;
2015
2016 st_delete(tbl, &n, &load);
2017 ele = get_autoload_data((VALUE)load, &ac);
2018 VM_ASSERT(ele);
2019 if (ele) {
2021 }
2022
2023 /*
2024 * we must delete here to avoid "already initialized" warnings
2025 * with parallel autoload. Using list_del_init here so list_del
2026 * works in autoload_c_free
2027 */
2028 list_del_init(&ac->cnode);
2029
2030 if (tbl->num_entries == 0) {
2031 n = autoload;
2032 st_delete(RCLASS_IV_TBL(mod), &n, &val);
2033 }
2034 }
2035}
2036
2037static VALUE
2038check_autoload_required(VALUE mod, ID id, const char **loadingpath)
2039{
2040 VALUE file;
2041 VALUE load = autoload_data(mod, id);
2042 struct autoload_data_i *ele;
2043 const char *loading;
2044
2045 if (!load || !(ele = get_autoload_data(load, 0))) {
2046 return 0;
2047 }
2048 file = ele->feature;
2049 Check_Type(file, T_STRING);
2050 if (!RSTRING_LEN(file) || !*RSTRING_PTR(file)) {
2051 rb_raise(rb_eArgError, "empty file name");
2052 }
2053
2054 /*
2055 * if somebody else is autoloading, we MUST wait for them, since
2056 * rb_provide_feature can provide a feature before autoload_const_set
2057 * completes. We must wait until autoload_const_set finishes in
2058 * the other thread.
2059 */
2060 if (ele->state && ele->state->thread != rb_thread_current()) {
2061 return load;
2062 }
2063
2064 loading = RSTRING_PTR(file);
2065 if (!rb_feature_provided(loading, &loading)) {
2066 return load;
2067 }
2068 if (loadingpath && loading) {
2069 *loadingpath = loading;
2070 return load;
2071 }
2072 return 0;
2073}
2074
2075static struct autoload_const *autoloading_const_entry(VALUE mod, ID id);
2076
2079{
2080 struct autoload_const *ac = autoloading_const_entry(mod, id);
2081 if (!ac) return FALSE;
2082
2083 if (value) {
2084 *value = ac->value;
2085 }
2086 if (flag) {
2087 *flag = ac->flag;
2088 }
2089 return TRUE;
2090}
2091
2092struct autoload_const *
2093autoloading_const_entry(VALUE mod, ID id)
2094{
2095 VALUE load = autoload_data(mod, id);
2096 struct autoload_data_i *ele;
2097 struct autoload_const *ac;
2098
2099 if (!load || !(ele = get_autoload_data(load, &ac))) {
2100 return 0;
2101 }
2102
2103 if (ele->state && ele->state->thread == rb_thread_current()) {
2104 if (ac->value != Qundef) {
2105 return ac;
2106 }
2107 }
2108 return 0;
2109}
2110
2111static int
2112autoload_defined_p(VALUE mod, ID id)
2113{
2115
2116 if (!ce || ce->value != Qundef) {
2117 return 0;
2118 }
2119 return !rb_autoloading_value(mod, id, NULL, NULL);
2120}
2121
2122static void const_tbl_update(struct autoload_const *);
2123
2124static VALUE
2125autoload_const_set(VALUE arg)
2126{
2127 struct autoload_const *ac = (struct autoload_const *)arg;
2128 VALUE klass = ac->mod;
2129 ID id = ac->id;
2130 check_before_mod_set(klass, id, ac->value, "constant");
2131 const_tbl_update(ac);
2132 return 0; /* ignored */
2133}
2134
2135static VALUE
2136autoload_require(VALUE arg)
2137{
2138 struct autoload_state *state = (struct autoload_state *)arg;
2139 struct autoload_const *ac = state->ac;
2140 struct autoload_data_i *ele;
2141
2142 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2143 /* this may release GVL and switch threads: */
2144 state->result = rb_funcall(rb_vm_top_self(), rb_intern("require"), 1,
2145 ele->feature);
2146
2147 return state->result;
2148}
2149
2150static VALUE
2151autoload_reset(VALUE arg)
2152{
2153 struct autoload_state *state = (struct autoload_state *)arg;
2154 int need_wakeups = 0;
2155 struct autoload_const *ac = state->ac;
2156 struct autoload_data_i *ele;
2157
2158 ele = rb_check_typeddata(ac->ad, &autoload_data_i_type);
2159 if (ele->state == state) {
2160 need_wakeups = 1;
2161 ele->state = 0;
2162 ele->fork_gen = 0;
2163 }
2164
2165 /* At the last, move a value defined in autoload to constant table */
2166 if (RTEST(state->result)) {
2167 struct autoload_const *next;
2168
2169 list_for_each_safe(&ele->constants, ac, next, cnode) {
2170 if (ac->value != Qundef) {
2171 autoload_const_set((VALUE)ac);
2172 }
2173 }
2174 }
2175
2176 /* wakeup any waiters we had */
2177 if (need_wakeups) {
2178 struct autoload_state *cur = 0, *nxt;
2179
2180 list_for_each_safe((struct list_head *)&state->waitq, cur, nxt, waitq) {
2181 VALUE th = cur->thread;
2182
2183 cur->thread = Qfalse;
2184 list_del_init(&cur->waitq); /* idempotent */
2185
2186 /*
2187 * cur is stored on the stack of cur->waiting_th,
2188 * do not touch cur after waking up waiting_th
2189 */
2191 }
2192 }
2193
2194 return 0; /* ignored */
2195}
2196
2197static VALUE
2198autoload_sleep(VALUE arg)
2199{
2200 struct autoload_state *state = (struct autoload_state *)arg;
2201
2202 /*
2203 * autoload_reset in other thread will resume us and remove us
2204 * from the waitq list
2205 */
2206 do {
2208 } while (state->thread != Qfalse);
2209
2210 return Qfalse;
2211}
2212
2213static VALUE
2214autoload_sleep_done(VALUE arg)
2215{
2216 struct autoload_state *state = (struct autoload_state *)arg;
2217
2218 if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) {
2219 list_del(&state->waitq); /* idempotent after list_del_init */
2220 }
2221
2222 return Qfalse;
2223}
2224
2225VALUE
2227{
2228 VALUE load, result;
2229 const char *loading = 0, *src;
2230 struct autoload_data_i *ele;
2231 struct autoload_const *ac;
2232 struct autoload_state state;
2233 int flag = -1;
2234 rb_const_entry_t *ce;
2235
2236 if (!autoload_defined_p(mod, id)) return Qfalse;
2237 load = check_autoload_required(mod, id, &loading);
2238 if (!load) return Qfalse;
2239 src = rb_sourcefile();
2240 if (src && loading && strcmp(src, loading) == 0) return Qfalse;
2241
2242 if ((ce = rb_const_lookup(mod, id))) {
2244 }
2245
2246 /* set ele->state for a marker of autoloading thread */
2247 if (!(ele = get_autoload_data(load, &ac))) {
2248 return Qfalse;
2249 }
2250 state.ac = ac;
2251 state.thread = rb_thread_current();
2252 if (!ele->state) {
2253 ele->state = &state;
2254 ele->fork_gen = GET_VM()->fork_gen;
2255
2256 /*
2257 * autoload_reset will wake up any threads added to this
2258 * iff the GVL is released during autoload_require
2259 */
2260 list_head_init((struct list_head *)&state.waitq);
2261 }
2262 else if (state.thread == ele->state->thread) {
2263 return Qfalse;
2264 }
2265 else {
2266 list_add_tail((struct list_head *)&ele->state->waitq, &state.waitq);
2267
2268 rb_ensure(autoload_sleep, (VALUE)&state,
2269 autoload_sleep_done, (VALUE)&state);
2270 }
2271
2272 /* autoload_data_i can be deleted by another thread while require */
2273 state.result = Qfalse;
2274 result = rb_ensure(autoload_require, (VALUE)&state,
2275 autoload_reset, (VALUE)&state);
2276
2277 if (flag > 0 && (ce = rb_const_lookup(mod, id))) {
2278 ce->flag |= flag;
2279 }
2280 RB_GC_GUARD(load);
2281 return result;
2282}
2283
2284VALUE
2286{
2287 return rb_autoload_at_p(mod, id, TRUE);
2288}
2289
2290VALUE
2292{
2293 VALUE load;
2294 struct autoload_data_i *ele;
2295
2296 while (!autoload_defined_p(mod, id)) {
2297 if (!recur) return Qnil;
2298 mod = RCLASS_SUPER(mod);
2299 if (!mod) return Qnil;
2300 }
2301 load = check_autoload_required(mod, id, 0);
2302 if (!load) return Qnil;
2303 return (ele = get_autoload_data(load, 0)) ? ele->feature : Qnil;
2304}
2305
2308{
2309 if (RB_CONST_DEPRECATED_P(ce) &&
2311 if (klass == rb_cObject) {
2312 rb_warn("constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
2313 }
2314 else {
2315 rb_warn("constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
2317 }
2318 }
2319}
2320
2321static VALUE
2322rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2323{
2324 VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
2325 if (c != Qundef) return c;
2326 return rb_const_missing(klass, ID2SYM(id));
2327}
2328
2329static VALUE
2330rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2331{
2332 VALUE value, tmp;
2333
2334 tmp = klass;
2335 while (RTEST(tmp)) {
2336 VALUE am = 0;
2337 rb_const_entry_t *ce;
2338
2339 while ((ce = rb_const_lookup(tmp, id))) {
2340 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2341 if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass;
2342 GET_EC()->private_const_reference = tmp;
2343 return Qundef;
2344 }
2345 rb_const_warn_if_deprecated(ce, tmp, id);
2346 value = ce->value;
2347 if (value == Qundef) {
2348 struct autoload_const *ac;
2349 if (am == tmp) break;
2350 am = tmp;
2351 ac = autoloading_const_entry(tmp, id);
2352 if (ac) return ac->value;
2353 rb_autoload_load(tmp, id);
2354 continue;
2355 }
2356 if (exclude && tmp == rb_cObject) {
2357 goto not_found;
2358 }
2359 return value;
2360 }
2361 if (!recurse) break;
2362 tmp = RCLASS_SUPER(tmp);
2363 }
2364
2365 not_found:
2366 GET_EC()->private_const_reference = 0;
2367 return Qundef;
2368}
2369
2370static VALUE
2371rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
2372{
2373 VALUE value;
2374
2375 if (klass == rb_cObject) exclude = FALSE;
2376 value = rb_const_search_from(klass, id, exclude, recurse, visibility);
2377 if (value != Qundef) return value;
2378 if (exclude) return value;
2379 if (BUILTIN_TYPE(klass) != T_MODULE) return value;
2380 /* search global const too, if klass is a module */
2381 return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
2382}
2383
2384VALUE
2386{
2387 return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
2388}
2389
2390VALUE
2392{
2393 return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
2394}
2395
2396VALUE
2398{
2399 return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
2400}
2401
2404{
2405 return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
2406}
2407
2410{
2411 return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
2412}
2413
2414NORETURN(static void undefined_constant(VALUE mod, VALUE name));
2415static void
2416undefined_constant(VALUE mod, VALUE name)
2417{
2418 rb_name_err_raise("constant %2$s::%1$s not defined",
2419 mod, name);
2420}
2421
2422static VALUE
2423rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
2424{
2425 while (RTEST(klass)) {
2426 rb_const_entry_t *ce;
2427
2428 while ((ce = rb_const_lookup(klass, id))) {
2429 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2430 return Qnil;
2431 }
2432 if (exclude && klass == rb_cObject) {
2433 goto not_found;
2434 }
2435 if (NIL_P(ce->file)) return rb_ary_new();
2436 return rb_assoc_new(ce->file, INT2NUM(ce->line));
2437 }
2438 if (!recurse) break;
2440 }
2441
2442 not_found:
2443 return Qnil;
2444}
2445
2446static VALUE
2447rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility)
2448{
2449 VALUE loc;
2450
2451 if (klass == rb_cObject) exclude = FALSE;
2452 loc = rb_const_location_from(klass, id, exclude, recurse, visibility);
2453 if (!NIL_P(loc)) return loc;
2454 if (exclude) return loc;
2455 if (BUILTIN_TYPE(klass) != T_MODULE) return loc;
2456 /* search global const too, if klass is a module */
2457 return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility);
2458}
2459
2460VALUE
2462{
2463 return rb_const_location(klass, id, FALSE, TRUE, FALSE);
2464}
2465
2468{
2469 return rb_const_location(klass, id, TRUE, FALSE, FALSE);
2470}
2471
2472/*
2473 * call-seq:
2474 * remove_const(sym) -> obj
2475 *
2476 * Removes the definition of the given constant, returning that
2477 * constant's previous value. If that constant referred to
2478 * a module, this will not change that module's name and can lead
2479 * to confusion.
2480 */
2481
2482VALUE
2484{
2485 const ID id = id_for_var(mod, name, a, constant);
2486
2487 if (!id) {
2488 undefined_constant(mod, name);
2489 }
2490 return rb_const_remove(mod, id);
2491}
2492
2493VALUE
2495{
2496 VALUE val;
2497 rb_const_entry_t *ce;
2498
2500 ce = rb_const_lookup(mod, id);
2501 if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2502 if (rb_const_defined_at(mod, id)) {
2503 rb_name_err_raise("cannot remove %2$s::%1$s",
2504 mod, ID2SYM(id));
2505 }
2506 undefined_constant(mod, ID2SYM(id));
2507 }
2508
2510
2511 val = ce->value;
2512 if (val == Qundef) {
2513 autoload_delete(mod, id);
2514 val = Qnil;
2515 }
2516 xfree(ce);
2517 return val;
2518}
2519
2520static int
2521cv_i_update(st_data_t *k, st_data_t *v, st_data_t a, int existing)
2522{
2523 if (existing) return ST_STOP;
2524 *v = a;
2525 return ST_CONTINUE;
2526}
2527
2529sv_i(ID key, VALUE v, void *a)
2530{
2532 st_table *tbl = a;
2533
2534 if (rb_is_const_id(key)) {
2535 st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2536 }
2537 return ID_TABLE_CONTINUE;
2538}
2539
2541rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
2542{
2543 if (rb_is_const_id(const_name) && !RB_CONST_PRIVATE_P((rb_const_entry_t *)const_value)) {
2544 rb_ary_push((VALUE)ary, ID2SYM(const_name));
2545 }
2546 return ID_TABLE_CONTINUE;
2547}
2548
2549static VALUE
2550rb_local_constants(VALUE mod)
2551{
2552 struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
2553 VALUE ary;
2554
2555 if (!tbl) return rb_ary_new2(0);
2556
2557 ary = rb_ary_new2(rb_id_table_size(tbl));
2558 rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
2559 return ary;
2560}
2561
2562void*
2564{
2565 st_table *tbl = data;
2566 if (!tbl) {
2567 tbl = st_init_numtable();
2568 }
2569 if (RCLASS_CONST_TBL(mod)) {
2571 }
2572 return tbl;
2573}
2574
2575void*
2577{
2578 VALUE tmp = mod;
2579 for (;;) {
2580 data = rb_mod_const_at(tmp, data);
2581 tmp = RCLASS_SUPER(tmp);
2582 if (!tmp) break;
2583 if (tmp == rb_cObject && mod != rb_cObject) break;
2584 }
2585 return data;
2586}
2587
2588static int
2589list_i(st_data_t key, st_data_t value, VALUE ary)
2590{
2591 ID sym = (ID)key;
2592 rb_const_entry_t *ce = (rb_const_entry_t *)value;
2593 if (RB_CONST_PUBLIC_P(ce)) rb_ary_push(ary, ID2SYM(sym));
2594 return ST_CONTINUE;
2595}
2596
2597VALUE
2598rb_const_list(void *data)
2599{
2600 st_table *tbl = data;
2601 VALUE ary;
2602
2603 if (!tbl) return rb_ary_new2(0);
2604 ary = rb_ary_new2(tbl->num_entries);
2605 st_foreach_safe(tbl, list_i, ary);
2606 st_free_table(tbl);
2607
2608 return ary;
2609}
2610
2611/*
2612 * call-seq:
2613 * mod.constants(inherit=true) -> array
2614 *
2615 * Returns an array of the names of the constants accessible in
2616 * <i>mod</i>. This includes the names of constants in any included
2617 * modules (example at start of section), unless the <i>inherit</i>
2618 * parameter is set to <code>false</code>.
2619 *
2620 * The implementation makes no guarantees about the order in which the
2621 * constants are yielded.
2622 *
2623 * IO.constants.include?(:SYNC) #=> true
2624 * IO.constants(false).include?(:SYNC) #=> false
2625 *
2626 * Also see Module#const_defined?.
2627 */
2628
2629VALUE
2631{
2632 bool inherit = true;
2633
2634 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
2635
2636 if (inherit) {
2637 return rb_const_list(rb_mod_const_of(mod, 0));
2638 }
2639 else {
2640 return rb_local_constants(mod);
2641 }
2642}
2643
2644static int
2645rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
2646{
2647 VALUE tmp;
2648 int mod_retry = 0;
2649 rb_const_entry_t *ce;
2650
2651 tmp = klass;
2652 retry:
2653 while (tmp) {
2654 if ((ce = rb_const_lookup(tmp, id))) {
2655 if (visibility && RB_CONST_PRIVATE_P(ce)) {
2656 return (int)Qfalse;
2657 }
2658 if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
2659 !rb_autoloading_value(tmp, id, NULL, NULL))
2660 return (int)Qfalse;
2661
2662 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
2663 return (int)Qfalse;
2664 }
2665
2666 return (int)Qtrue;
2667 }
2668 if (!recurse) break;
2669 tmp = RCLASS_SUPER(tmp);
2670 }
2671 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
2672 mod_retry = 1;
2673 tmp = rb_cObject;
2674 goto retry;
2675 }
2676 return (int)Qfalse;
2677}
2678
2679int
2681{
2682 return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
2683}
2684
2685int
2687{
2688 return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
2689}
2690
2691int
2693{
2694 return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
2695}
2696
2699{
2700 return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
2701}
2702
2703static void
2704check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
2705{
2707}
2708
2709static void set_namespace_path(VALUE named_namespace, VALUE name);
2710
2712set_namespace_path_i(ID id, VALUE v, void *payload)
2713{
2715 VALUE value = ce->value;
2716 int has_permanent_classpath;
2717 VALUE parental_path = *((VALUE *) payload);
2718 if (!rb_is_const_id(id)) {
2719 return ID_TABLE_CONTINUE;
2720 }
2721 if (!rb_namespace_p(value)) {
2722 return ID_TABLE_CONTINUE;
2723 }
2724 classname(value, &has_permanent_classpath);
2725 if (has_permanent_classpath) {
2726 return ID_TABLE_CONTINUE;
2727 }
2728 set_namespace_path(value, build_const_path(parental_path, id));
2729 if (RCLASS_IV_TBL(value)) {
2730 st_data_t tmp = tmp_classpath;
2731 st_delete(RCLASS_IV_TBL(value), &tmp, 0);
2732 }
2733
2734 return ID_TABLE_CONTINUE;
2735}
2736
2737/*
2738 * Assign permanent classpaths to all namespaces that are directly or indirectly
2739 * nested under +named_namespace+. +named_namespace+ must have a permanent
2740 * classpath.
2741 */
2742static void
2743set_namespace_path(VALUE named_namespace, VALUE namespace_path)
2744{
2745 struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
2746 if (!RCLASS_IV_TBL(named_namespace)) {
2747 RCLASS_IV_TBL(named_namespace) = st_init_numtable();
2748 }
2749 rb_class_ivar_set(named_namespace, classpath, namespace_path);
2750 if (const_table) {
2751 rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
2752 }
2753}
2754
2755void
2757{
2758 rb_const_entry_t *ce;
2759 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2760
2761 if (NIL_P(klass)) {
2762 rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
2763 QUOTE_ID(id));
2764 }
2765
2766 check_before_mod_set(klass, id, val, "constant");
2767 if (!tbl) {
2771 rb_id_table_insert(tbl, id, (VALUE)ce);
2772 setup_const_entry(ce, klass, val, CONST_PUBLIC);
2773 }
2774 else {
2775 struct autoload_const ac = {
2776 .mod = klass, .id = id,
2777 .value = val, .flag = CONST_PUBLIC,
2778 /* fill the rest with 0 */
2779 };
2780 const_tbl_update(&ac);
2781 }
2782 /*
2783 * Resolve and cache class name immediately to resolve ambiguity
2784 * and avoid order-dependency on const_tbl
2785 */
2786 if (rb_cObject && rb_namespace_p(val)) {
2787 int val_path_permanent;
2788 VALUE val_path = classname(val, &val_path_permanent);
2789 if (NIL_P(val_path) || !val_path_permanent) {
2790 if (klass == rb_cObject) {
2791 set_namespace_path(val, rb_id2str(id));
2792 }
2793 else {
2794 int parental_path_permanent;
2795 VALUE parental_path = classname(klass, &parental_path_permanent);
2796 if (!NIL_P(parental_path)) {
2797 if (parental_path_permanent && !val_path_permanent) {
2798 set_namespace_path(val, build_const_path(parental_path, id));
2799 }
2800 else if (!parental_path_permanent && NIL_P(val_path)) {
2801 rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
2802 }
2803 }
2804 }
2805 }
2806 }
2807}
2808
2809static struct autoload_data_i *
2810current_autoload_data(VALUE mod, ID id, struct autoload_const **acp)
2811{
2812 struct autoload_data_i *ele;
2813 VALUE load = autoload_data(mod, id);
2814 if (!load) return 0;
2815 ele = get_autoload_data(load, acp);
2816 if (!ele) return 0;
2817 /* for autoloading thread, keep the defined value to autoloading storage */
2818 if (ele->state && (ele->state->thread == rb_thread_current())) {
2819 return ele;
2820 }
2821 return 0;
2822}
2823
2824static void
2825const_tbl_update(struct autoload_const *ac)
2826{
2827 VALUE value;
2828 VALUE klass = ac->mod;
2829 VALUE val = ac->value;
2830 ID id = ac->id;
2831 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2832 rb_const_flag_t visibility = ac->flag;
2833 rb_const_entry_t *ce;
2834
2835 if (rb_id_table_lookup(tbl, id, &value)) {
2836 ce = (rb_const_entry_t *)value;
2837 if (ce->value == Qundef) {
2838 struct autoload_data_i *ele = current_autoload_data(klass, id, &ac);
2839
2840 if (ele) {
2842
2843 ac->value = val; /* autoload_i is non-WB-protected */
2844 ac->file = rb_source_location(&ac->line);
2845 }
2846 else {
2847 /* otherwise autoloaded constant, allow to override */
2848 autoload_delete(klass, id);
2849 ce->flag = visibility;
2850 RB_OBJ_WRITE(klass, &ce->value, val);
2851 RB_OBJ_WRITE(klass, &ce->file, ac->file);
2852 ce->line = ac->line;
2853 }
2854 return;
2855 }
2856 else {
2857 VALUE name = QUOTE_ID(id);
2858 visibility = ce->flag;
2859 if (klass == rb_cObject)
2860 rb_warn("already initialized constant %"PRIsVALUE"", name);
2861 else
2862 rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
2864 if (!NIL_P(ce->file) && ce->line) {
2866 "previous definition of %"PRIsVALUE" was here", name);
2867 }
2868 }
2870 setup_const_entry(ce, klass, val, visibility);
2871 }
2872 else {
2874
2876 rb_id_table_insert(tbl, id, (VALUE)ce);
2877 setup_const_entry(ce, klass, val, visibility);
2878 }
2879}
2880
2881static void
2882setup_const_entry(rb_const_entry_t *ce, VALUE klass, VALUE val,
2883 rb_const_flag_t visibility)
2884{
2885 ce->flag = visibility;
2886 RB_OBJ_WRITE(klass, &ce->value, val);
2888}
2889
2890void
2892{
2893 ID id = rb_intern(name);
2894
2895 if (!rb_is_const_id(id)) {
2896 rb_warn("rb_define_const: invalid name `%s' for constant", name);
2897 }
2899 rb_const_set(klass, id, val);
2900}
2901
2902void
2904{
2906}
2907
2908static void
2909set_const_visibility(VALUE mod, int argc, const VALUE *argv,
2911{
2912 int i;
2913 rb_const_entry_t *ce;
2914 ID id;
2915
2917 if (argc == 0) {
2918 rb_warning("%"PRIsVALUE" with no argument is just ignored",
2920 return;
2921 }
2922
2923 for (i = 0; i < argc; i++) {
2924 struct autoload_const *ac;
2925 VALUE val = argv[i];
2926 id = rb_check_id(&val);
2927 if (!id) {
2928 if (i > 0) {
2930 }
2931
2932 undefined_constant(mod, val);
2933 }
2934 if ((ce = rb_const_lookup(mod, id))) {
2935 ce->flag &= ~mask;
2936 ce->flag |= flag;
2937 if (ce->value == Qundef) {
2938 struct autoload_data_i *ele;
2939
2940 ele = current_autoload_data(mod, id, &ac);
2941 if (ele) {
2942 ac->flag &= ~mask;
2943 ac->flag |= flag;
2944 }
2945 }
2946 }
2947 else {
2948 if (i > 0) {
2950 }
2951 undefined_constant(mod, ID2SYM(id));
2952 }
2953 }
2955}
2956
2957void
2959{
2960 rb_const_entry_t *ce;
2961 ID id;
2962 long len = strlen(name);
2963
2965 if (!(id = rb_check_id_cstr(name, len, NULL))) {
2966 undefined_constant(mod, rb_fstring_new(name, len));
2967 }
2968 if (!(ce = rb_const_lookup(mod, id))) {
2969 undefined_constant(mod, ID2SYM(id));
2970 }
2971 ce->flag |= CONST_DEPRECATED;
2972}
2973
2974/*
2975 * call-seq:
2976 * mod.private_constant(symbol, ...) => mod
2977 *
2978 * Makes a list of existing constants private.
2979 */
2980
2981VALUE
2983{
2984 set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
2985 return obj;
2986}
2987
2988/*
2989 * call-seq:
2990 * mod.public_constant(symbol, ...) => mod
2991 *
2992 * Makes a list of existing constants public.
2993 */
2994
2995VALUE
2997{
2998 set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
2999 return obj;
3000}
3001
3002/*
3003 * call-seq:
3004 * mod.deprecate_constant(symbol, ...) => mod
3005 *
3006 * Makes a list of existing constants deprecated. Attempt
3007 * to refer to them will produce a warning.
3008 *
3009 * module HTTP
3010 * NotFound = Exception.new
3011 * NOT_FOUND = NotFound # previous version of the library used this name
3012 *
3013 * deprecate_constant :NOT_FOUND
3014 * end
3015 *
3016 * HTTP::NOT_FOUND
3017 * # warning: constant HTTP::NOT_FOUND is deprecated
3018 *
3019 */
3020
3021VALUE
3023{
3024 set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
3025 return obj;
3026}
3027
3028static VALUE
3029original_module(VALUE c)
3030{
3031 if (RB_TYPE_P(c, T_ICLASS))
3032 return RBASIC(c)->klass;
3033 return c;
3034}
3035
3036static int
3037cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
3038{
3039 if (!RCLASS_IV_TBL(klass)) return 0;
3040 return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v);
3041}
3042
3043static VALUE
3044cvar_front_klass(VALUE klass)
3045{
3046 if (FL_TEST(klass, FL_SINGLETON)) {
3048 if (rb_namespace_p(obj)) {
3049 return obj;
3050 }
3051 }
3052 return RCLASS_SUPER(klass);
3053}
3054
3055static void
3056cvar_overtaken(VALUE front, VALUE target, ID id)
3057{
3058 if (front && target != front) {
3059 st_data_t did = (st_data_t)id;
3060
3061 if (RTEST(ruby_verbose) && original_module(front) != original_module(target)) {
3062 rb_warning("class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
3063 ID2SYM(id), rb_class_name(original_module(front)),
3064 rb_class_name(original_module(target)));
3065 }
3066 if (BUILTIN_TYPE(front) == T_CLASS) {
3067 st_delete(RCLASS_IV_TBL(front), &did, 0);
3068 }
3069 }
3070}
3071
3072#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
3073 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
3074 if (cvar_lookup_at(klass, id, (v))) { \
3075 r; \
3076 } \
3077 }
3078
3079#define CVAR_LOOKUP(v,r) do {\
3080 if (cvar_lookup_at(klass, id, (v))) {r;}\
3081 CVAR_FOREACH_ANCESTORS(klass, v, r);\
3082} while(0)
3083
3084void
3086{
3087 VALUE tmp, front = 0, target = 0;
3088
3089 tmp = klass;
3090 CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
3091 if (target) {
3092 cvar_overtaken(front, target, id);
3093 }
3094 else {
3095 target = tmp;
3096 }
3097
3098 check_before_mod_set(target, id, val, "class variable");
3099 if (!RCLASS_IV_TBL(target)) {
3100 RCLASS_IV_TBL(target) = st_init_numtable();
3101 }
3102
3103 rb_class_ivar_set(target, id, val);
3104}
3105
3106VALUE
3108{
3109 VALUE tmp, front = 0, target = 0;
3110 st_data_t value;
3111
3112 tmp = klass;
3113 CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
3114 if (!target) {
3115 rb_name_err_raise("uninitialized class variable %1$s in %2$s",
3116 tmp, ID2SYM(id));
3117 }
3118 cvar_overtaken(front, target, id);
3119 return (VALUE)value;
3120}
3121
3122VALUE
3124{
3125 if (!klass) return Qfalse;
3126 CVAR_LOOKUP(0,return Qtrue);
3127 return Qfalse;
3128}
3129
3130static ID
3131cv_intern(VALUE klass, const char *name)
3132{
3133 ID id = rb_intern(name);
3134 if (!rb_is_class_id(id)) {
3135 rb_name_err_raise("wrong class variable name %1$s",
3137 }
3138 return id;
3139}
3140
3141void
3142rb_cv_set(VALUE klass, const char *name, VALUE val)
3143{
3144 ID id = cv_intern(klass, name);
3145 rb_cvar_set(klass, id, val);
3146}
3147
3148VALUE
3150{
3151 ID id = cv_intern(klass, name);
3152 return rb_cvar_get(klass, id);
3153}
3154
3155void
3157{
3158 ID id = cv_intern(klass, name);
3159 rb_cvar_set(klass, id, val);
3160}
3161
3162static int
3163cv_i(st_data_t k, st_data_t v, st_data_t a)
3164{
3165 ID key = (ID)k;
3166 st_table *tbl = (st_table *)a;
3167
3168 if (rb_is_class_id(key)) {
3169 st_update(tbl, (st_data_t)key, cv_i_update, 0);
3170 }
3171 return ST_CONTINUE;
3172}
3173
3174static void*
3175mod_cvar_at(VALUE mod, void *data)
3176{
3177 st_table *tbl = data;
3178 if (!tbl) {
3179 tbl = st_init_numtable();
3180 }
3181 if (RCLASS_IV_TBL(mod)) {
3183 }
3184 return tbl;
3185}
3186
3187static void*
3188mod_cvar_of(VALUE mod, void *data)
3189{
3190 VALUE tmp = mod;
3191 if (FL_TEST(mod, FL_SINGLETON)) {
3192 if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) {
3193 data = mod_cvar_at(tmp, data);
3194 tmp = cvar_front_klass(tmp);
3195 }
3196 }
3197 for (;;) {
3198 data = mod_cvar_at(tmp, data);
3199 tmp = RCLASS_SUPER(tmp);
3200 if (!tmp) break;
3201 }
3202 return data;
3203}
3204
3205static int
3206cv_list_i(st_data_t key, st_data_t value, VALUE ary)
3207{
3208 ID sym = (ID)key;
3209 rb_ary_push(ary, ID2SYM(sym));
3210 return ST_CONTINUE;
3211}
3212
3213static VALUE
3214cvar_list(void *data)
3215{
3216 st_table *tbl = data;
3217 VALUE ary;
3218
3219 if (!tbl) return rb_ary_new2(0);
3220 ary = rb_ary_new2(tbl->num_entries);
3221 st_foreach_safe(tbl, cv_list_i, ary);
3222 st_free_table(tbl);
3223
3224 return ary;
3225}
3226
3227/*
3228 * call-seq:
3229 * mod.class_variables(inherit=true) -> array
3230 *
3231 * Returns an array of the names of class variables in <i>mod</i>.
3232 * This includes the names of class variables in any included
3233 * modules, unless the <i>inherit</i> parameter is set to
3234 * <code>false</code>.
3235 *
3236 * class One
3237 * @@var1 = 1
3238 * end
3239 * class Two < One
3240 * @@var2 = 2
3241 * end
3242 * One.class_variables #=> [:@@var1]
3243 * Two.class_variables #=> [:@@var2, :@@var1]
3244 * Two.class_variables(false) #=> [:@@var2]
3245 */
3246
3247VALUE
3249{
3250 bool inherit = true;
3251 st_table *tbl;
3252
3253 if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]);
3254 if (inherit) {
3255 tbl = mod_cvar_of(mod, 0);
3256 }
3257 else {
3258 tbl = mod_cvar_at(mod, 0);
3259 }
3260 return cvar_list(tbl);
3261}
3262
3263/*
3264 * call-seq:
3265 * remove_class_variable(sym) -> obj
3266 *
3267 * Removes the definition of the <i>sym</i>, returning that
3268 * constant's value.
3269 *
3270 * class Dummy
3271 * @@var = 99
3272 * puts @@var
3273 * remove_class_variable(:@@var)
3274 * p(defined? @@var)
3275 * end
3276 *
3277 * <em>produces:</em>
3278 *
3279 * 99
3280 * nil
3281 */
3282
3283VALUE
3285{
3286 const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
3287 st_data_t val, n = id;
3288
3289 if (!id) {
3290 not_defined:
3291 rb_name_err_raise("class variable %1$s not defined for %2$s",
3292 mod, name);
3293 }
3295 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
3296 return (VALUE)val;
3297 }
3298 if (rb_cvar_defined(mod, id)) {
3299 rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
3300 }
3301 goto not_defined;
3302}
3303
3304VALUE
3306{
3308
3309 if (!id) {
3310 if (RTEST(ruby_verbose))
3311 rb_warning("instance variable %s not initialized", name);
3312 return Qnil;
3313 }
3314 return rb_ivar_get(obj, id);
3315}
3316
3317VALUE
3318rb_iv_set(VALUE obj, const char *name, VALUE val)
3319{
3320 ID id = rb_intern(name);
3321
3322 return rb_ivar_set(obj, id, val);
3323}
3324
3325/* tbl = xx(obj); tbl[key] = value; */
3326int
3328{
3329 st_table *tbl = RCLASS_IV_TBL(obj);
3330 int result = st_insert(tbl, (st_data_t)key, (st_data_t)value);
3331 RB_OBJ_WRITTEN(obj, Qundef, value);
3332 return result;
3333}
3334
3335static int
3336tbl_copy_i(st_data_t key, st_data_t value, st_data_t data)
3337{
3338 RB_OBJ_WRITTEN((VALUE)data, Qundef, (VALUE)value);
3339 return ST_CONTINUE;
3340}
3341
3342void
3344{
3345 st_table *orig_tbl = RCLASS_IV_TBL(src);
3346 st_table *new_tbl = st_copy(orig_tbl);
3347 st_foreach(new_tbl, tbl_copy_i, (st_data_t)dst);
3348 RCLASS_IV_TBL(dst) = new_tbl;
3349}
3350
3353{
3354 struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3355 VALUE val;
3356
3357 if (tbl && rb_id_table_lookup(tbl, id, &val)) {
3358 return (rb_const_entry_t *)val;
3359 }
3360 return 0;
3361}
#define sym(x)
Definition: date_core.c:3717
#define mod(x, y)
Definition: date_strftime.c:28
#define recur(fmt)
enum @73::@75::@76 mask
struct RIMemo * ptr
Definition: debug.c:65
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
int count
Definition: encoding.c:57
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:988
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_class_modify_check(VALUE)
Asserts that klass is not a frozen class.
Definition: eval.c:438
ID rb_frame_callee(void)
The name of the current method.
Definition: eval.c:1200
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Definition: variable.c:511
@ ROBJECT_EMBED
Definition: ruby.h:917
@ ROBJECT_EMBED_LEN_MAX
Definition: ruby.h:916
VALUE rb_gv_set(const char *name, VALUE val)
Definition: variable.c:671
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
void rb_define_variable(const char *name, VALUE *var)
Definition: variable.c:499
void rb_define_global_const(const char *name, VALUE val)
Definition: variable.c:2903
const char * rb_obj_classname(VALUE obj)
Definition: variable.c:289
VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
Definition: variable.c:3318
void rb_define_const(VALUE klass, const char *name, VALUE val)
Definition: variable.c:2891
void rb_define_readonly_variable(const char *name, const VALUE *var)
Definition: variable.c:505
VALUE rb_gv_get(const char *name)
Definition: variable.c:680
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Definition: variable.c:480
VALUE rb_iv_get(VALUE obj, const char *name)
Definition: variable.c:3305
VALUE rb_cModule
Module class.
Definition: ruby.h:2036
const char * rb_class2name(VALUE klass)
Definition: variable.c:280
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
_Bool rb_warning_category_enabled_p(rb_warning_category_t category)
Definition: error.c:166
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:1515
VALUE rb_eTypeError
Definition: error.c:924
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:1530
VALUE rb_eNameError
Definition: error.c:929
VALUE rb_eRuntimeError
Definition: error.c:922
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:891
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
Definition: object.c:202
void st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
Definition: hash.c:1294
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
Definition: id_table.c:256
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
Definition: id_table.c:226
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
size_t rb_id_table_size(const struct rb_id_table *tbl)
Definition: id_table.c:117
struct rb_id_table * rb_id_table_create(size_t capa)
Definition: id_table.c:95
int rb_id_table_delete(struct rb_id_table *tbl, ID id)
Definition: id_table.c:262
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_id_table_iterator_result
Definition: id_table.h:8
@ ID_TABLE_CONTINUE
Definition: id_table.h:9
MJIT_STATIC void rb_vm_pop_cfunc_frame(void)
Definition: vm.c:590
const char * name
Definition: nkf.c:208
__uint32_t uint32_t
#define ROBJECT(obj)
#define rb_str_new2
#define MEMCPY(p1, p2, type, n)
#define list_del(n)
#define NULL
#define FL_SINGLETON
#define rb_funcallv(recv, mid, argc, argv)
@ RB_WARN_CATEGORY_DEPRECATED
#define RSTRING_LEN(str)
VALUE rb_thread_wakeup_alive(VALUE)
Definition: thread.c:2548
#define list_del_init(n)
#define FL_EXIVAR
#define _(args)
#define RTEST(v)
#define ALLOCV_END(v)
#define RCLASS_SUPER(c)
#define FL_TEST(x, f)
unsigned long st_data_t
void rb_gc_mark_maybe(VALUE)
Definition: gc.c:5060
#define RBASIC(obj)
void rb_compile_warn(const char *, int, const char *,...) __attribute__((format(printf
size_t strlen(const char *)
int strcmp(const char *, const char *)
#define T_STRING
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:2037
VALUE rb_backref_get(void)
Definition: vm.c:1304
#define offsetof(TYPE, MEMBER)
#define xfree
#define ROBJECT_IV_INDEX_TBL(o)
#define QUOTE_ID(id)
#define Qundef
#define RB_SPECIAL_CONST_P(x)
#define rb_str_cat2
const char * rb_sourcefile(void)
Definition: vm.c:1331
const VALUE VALUE obj
int rb_feature_provided(const char *, const char **)
Definition: load.c:562
#define rb_check_frozen(obj)
#define RB_CONST_PRIVATE_P(ce)
#define FL_SET(x, f)
#define RB_CONST_DEPRECATED_P(ce)
#define st_is_member(table, key)
#define RSTRING_PTR(str)
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:7079
#define xrealloc
void rb_clear_constant_cache(void)
Definition: vm_method.c:87
#define GET_EC()
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
#define NIL_P(v)
void rb_gvar_marker_t(VALUE *var)
#define rb_name_err_raise(mesg, recv, name)
#define VM_ASSERT(expr)
#define ID2SYM(x)
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2471
#define list_add_tail(h, n)
#define REALLOC_N(var, type, n)
void rb_gvar_setter_t(VALUE val, ID id, VALUE *data)
const char size_t n
#define ruby_verbose
#define rb_intern_const(str)
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
__inline__ const void *__restrict__ src
#define xmalloc
#define T_MODULE
#define GET_VM()
#define FL_UNSET(x, f)
uint32_t i
__int32_t int32_t
#define char
VALUE rb_fstring(VALUE)
Definition: string.c:312
__inline__ const void *__restrict__ size_t len
#define ALLOC_N(type, n)
#define OBJ_FREEZE(x)
VALUE rb_block_proc(void)
Definition: proc.c:837
#define INT2NUM(x)
#define ZALLOC(type)
#define RCLASS_IV_TBL(c)
#define RB_OBJ_WRITE(a, slot, b)
#define T_ICLASS
#define ROBJ_TRANSIENT_SET(obj)
VALUE rb_gc_location(VALUE)
Definition: gc.c:8127
#define RB_GC_GUARD(v)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define PRIsVALUE
unsigned long long rb_serial_t
#define rb_ary_new3
#define rb_funcall(recv, mid, argc,...)
int VALUE v
VALUE rb_ary_new(void)
Definition: array.c:723
void rb_gc_update_tbl_refs(st_table *ptr)
Definition: gc.c:7999
#define rb_scan_args(argc, argvp, fmt,...)
#define list_empty(h)
#define list_for_each_safe(h, i, nxt, member)
ID rb_intern2(const char *, long)
Definition: symbol.c:653
void rb_gc_mark(VALUE)
Definition: gc.c:5228
#define rb_intern(str)
#define RCLASS_CONST_TBL(c)
#define INT_MAX
#define UNREACHABLE_RETURN(val)
VALUE ID VALUE old
#define ALLOCV_N(type, v, n)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define RCLASS_EXT(c)
#define TRUE
#define FALSE
#define Qtrue
#define ROBJ_TRANSIENT_UNSET(obj)
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
VALUE rb_hash_delete(VALUE, VALUE)
Definition: hash.c:2344
void rb_thread_sleep_deadly(void)
Definition: thread.c:1320
#define RB_NO_KEYWORDS
VALUE rb_fstring_new(const char *ptr, long len)
Definition: string.c:396
struct rb_call_cache buf
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
#define Qnil
#define Qfalse
int rb_match_nth_defined(int nth, VALUE match)
Definition: re.c:1317
#define DATA_PTR(dta)
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
#define RB_CONST_PUBLIC_P(ce)
#define T_OBJECT
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
st_data_t st_index_t
VALUE rb_source_location(int *pline)
Definition: vm.c:1360
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
VALUE rb_thread_current(void)
Definition: thread.c:2675
#define RB_TYPE_P(obj, type)
#define SPECIAL_CONST_P(x)
#define ALLOC(type)
void rb_gc_mark_movable(VALUE)
Definition: gc.c:5222
#define TypedData_Make_Struct(klass, type, data_type, sval)
#define MJIT_FUNC_EXPORTED
const VALUE * argv
__inline__ int
#define T_CLASS
#define CLASS_OF(v)
int rb_match_count(VALUE match)
Definition: re.c:1307
#define Check_Type(v, t)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
VALUE rb_gvar_getter_t(ID id, VALUE *data)
#define ROBJ_TRANSIENT_P(obj)
#define assert
#define rb_check_arity
#define QUOTE(str)
VALUE rb_eval_cmd_kw(VALUE, VALUE, int)
Definition: vm_eval.c:1801
#define ROBJECT_IVPTR(o)
#define RB_BUILTIN_TYPE(x)
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
unsigned long ID
#define RCLASS_IV_INDEX_TBL(c)
const char *void rb_warning(const char *,...) __attribute__((format(printf
#define rb_fstring_cstr(str)
#define RUBY_FUNC_EXPORTED
VALUE ID id
#define rb_name_err_raise_str(mesg, recv, name)
#define rb_ary_new2
#define BUILTIN_TYPE(x)
#define rb_str_new_cstr(str)
#define RB_OBJ_WRITTEN(a, oldv, b)
#define ASSUME(x)
#define ROBJECT_NUMIV(o)
ID rb_to_id(VALUE)
Definition: string.c:11146
#define RB_DEBUG_COUNTER_INC(type)
void rb_vm_inc_const_missing_count(void)
Definition: vm.c:386
void rb_mark_tbl_no_pin(struct st_table *)
Definition: gc.c:5027
void st_free_table(st_table *tab)
Definition: st.c:709
size_t st_memsize(const st_table *tab)
Definition: st.c:719
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1418
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1251
st_table * st_init_numtable(void)
Definition: st.c:653
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1717
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1509
st_table * st_copy(st_table *old_tab)
Definition: st.c:1320
struct list_node cnode
Definition: variable.c:1801
rb_const_flag_t flag
Definition: variable.c:1807
rb_serial_t fork_gen
Definition: variable.c:1822
struct autoload_state * state
Definition: variable.c:1821
struct list_head constants
Definition: variable.c:1823
struct autoload_const * ac
Definition: variable.c:1813
struct list_node waitq
Definition: variable.c:1816
struct gen_ivtbl * ivtbl
Definition: variable.c:1386
rb_ivar_foreach_callback_func * func
Definition: variable.c:1387
st_data_t arg
Definition: variable.c:1388
VALUE obj
Definition: variable.c:1421
st_table * iv_index_tbl
Definition: variable.c:1422
struct gen_ivtbl * ivtbl
Definition: variable.c:1423
struct gen_ivtbl * ivtbl
Definition: variable.c:41
st_table * iv_index_tbl
Definition: variable.c:40
st_data_t index
Definition: variable.c:43
union ivar_update::@231 u
int iv_extended
Definition: variable.c:44
st_data_t arg
Definition: variable.c:1352
rb_ivar_foreach_callback_func * func
Definition: variable.c:1351
VALUE value
rb_const_flag_t flag
VALUE file
int line
ID id
struct rb_global_variable * var
rb_gvar_marker_t * marker
Definition: variable.c:307
rb_gvar_getter_t * getter
Definition: variable.c:305
rb_gvar_setter_t * setter
Definition: variable.c:306
struct trace_var * trace
Definition: variable.c:308
struct trace_var * trace
Definition: variable.c:626
VALUE val
Definition: variable.c:627
void(* func)(VALUE arg, VALUE val)
Definition: variable.c:296
VALUE data
Definition: variable.c:297
int removed
Definition: variable.c:295
struct trace_var * next
Definition: variable.c:298
int rb_is_instance_id(ID id)
Definition: symbol.c:872
int rb_is_const_id(ID id)
Definition: symbol.c:854
int rb_is_class_id(ID id)
Definition: symbol.c:860
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
VALUE rb_mod_remove_cvar(VALUE mod, VALUE name)
Definition: variable.c:3284
VALUE rb_const_get_at(VALUE klass, ID id)
Definition: variable.c:2397
NORETURN(static void uninitialized_constant(VALUE, VALUE))
VALUE rb_obj_instance_variables(VALUE obj)
Definition: variable.c:1579
VALUE rb_f_untrace_var(int argc, const VALUE *argv)
Definition: variable.c:574
VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:2996
VALUE rb_const_list(void *data)
Definition: variable.c:2598
void rb_gvar_val_marker(VALUE *var)
Definition: variable.c:386
MJIT_FUNC_EXPORTED VALUE rb_public_const_get_from(VALUE klass, ID id)
Definition: variable.c:2403
VALUE rb_cvar_defined(VALUE klass, ID id)
Definition: variable.c:3123
VALUE rb_path2class(const char *path)
Definition: variable.c:268
#define CVAR_LOOKUP(v, r)
Definition: variable.c:3079
rb_gvar_setter_t * rb_gvar_setter_function_of(const struct rb_global_entry *entry)
Definition: variable.c:708
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Definition: variable.c:1447
VALUE rb_gvar_undef_getter(ID id, VALUE *_)
Definition: variable.c:349
bool rb_gvar_is_traced(const struct rb_global_entry *entry)
Definition: variable.c:714
VALUE(* fallback_func)(VALUE obj, VALUE name)
Definition: variable.c:127
VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
Definition: variable.c:1300
void rb_alias_variable(ID name1, ID name2)
Definition: variable.c:756
void rb_set_class_path(VALUE klass, VALUE under, const char *name)
Definition: variable.c:218
#define id_for_var_message(obj, name, type, message)
Definition: variable.c:1592
MJIT_FUNC_EXPORTED void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
Definition: variable.c:2307
VALUE rb_attr_delete(VALUE obj, ID id)
Definition: variable.c:1126
MJIT_FUNC_EXPORTED struct st_table * rb_ivar_generic_ivtbl(void)
Definition: variable.c:803
rb_gvar_getter_t * rb_gvar_getter_function_of(const struct rb_global_entry *entry)
Definition: variable.c:702
void rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
Definition: variable.c:1308
void rb_deprecate_constant(VALUE mod, const char *name)
Definition: variable.c:2958
void rb_gc_mark_global_tbl(void)
Definition: variable.c:434
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
Definition: variable.c:2630
MJIT_FUNC_EXPORTED int rb_public_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2698
VALUE rb_gvar_val_getter(ID id, VALUE *data)
Definition: variable.c:373
VALUE rb_const_get(VALUE klass, ID id)
Definition: variable.c:2391
VALUE rb_f_trace_var(int argc, const VALUE *argv)
Definition: variable.c:528
RUBY_FUNC_EXPORTED size_t rb_generic_ivar_memsize(VALUE obj)
Definition: variable.c:1010
MJIT_FUNC_EXPORTED struct rb_global_entry * rb_global_entry(ID id)
Definition: variable.c:326
void rb_gvar_var_marker(VALUE *var)
Definition: variable.c:406
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
Definition: variable.c:1035
void rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
Definition: variable.c:983
void rb_mark_generic_ivar(VALUE obj)
Definition: variable.c:973
VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:2982
MJIT_FUNC_EXPORTED VALUE rb_gvar_get(struct rb_global_entry *entry)
Definition: variable.c:619
VALUE rb_search_class_path(VALUE klass)
Definition: variable.c:175
int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg)
Definition: variable.c:1347
int rb_class_ivar_set(VALUE obj, ID key, VALUE value)
Definition: variable.c:3327
void rb_gvar_val_setter(VALUE val, ID id, VALUE *_)
Definition: variable.c:379
void rb_gvar_undef_marker(VALUE *var)
Definition: variable.c:368
void rb_cvar_set(VALUE klass, ID id, VALUE val)
Definition: variable.c:3085
void rb_iv_tbl_copy(VALUE dst, VALUE src)
Definition: variable.c:3343
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
VALUE rb_autoload_at_p(VALUE mod, ID id, int recur)
Definition: variable.c:2291
void rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
Definition: variable.c:357
MJIT_FUNC_EXPORTED int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag)
Definition: variable.c:2078
VALUE rb_cvar_get(VALUE klass, ID id)
Definition: variable.c:3107
VALUE rb_mod_name(VALUE mod)
Definition: variable.c:102
void rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
Definition: variable.c:1489
VALUE rb_ivar_get(VALUE obj, ID id)
Definition: variable.c:1070
void Init_var_tables(void)
Definition: variable.c:48
MJIT_FUNC_EXPORTED VALUE rb_const_source_location_at(VALUE klass, ID id)
Definition: variable.c:2467
MJIT_FUNC_EXPORTED rb_const_entry_t * rb_const_lookup(VALUE klass, ID id)
Definition: variable.c:3352
VALUE rb_class_path_cached(VALUE klass)
Definition: variable.c:162
VALUE rb_autoload_load(VALUE mod, ID id)
Definition: variable.c:2226
void rb_obj_transient_heap_evacuate(VALUE obj, int promote)
Definition: variable.c:1215
void rb_autoload_str(VALUE mod, ID id, VALUE file)
Definition: variable.c:1937
VALUE rb_const_remove(VALUE mod, ID id)
Definition: variable.c:2494
VALUE rb_const_get_from(VALUE klass, ID id)
Definition: variable.c:2385
void rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
Definition: variable.c:198
MJIT_FUNC_EXPORTED VALUE rb_gvar_set(struct rb_global_entry *entry, VALUE val)
Definition: variable.c:654
int rb_const_defined(VALUE klass, ID id)
Definition: variable.c:2686
void rb_const_set(VALUE klass, ID id, VALUE val)
Definition: variable.c:2756
VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name)
Definition: variable.c:1634
MJIT_FUNC_EXPORTED VALUE rb_gvar_defined(struct rb_global_entry *entry)
Definition: variable.c:695
VALUE rb_path_to_class(VALUE pathname)
Definition: variable.c:226
VALUE rb_autoload_p(VALUE mod, ID id)
Definition: variable.c:2285
#define id_for_var(obj, name, part, type)
Definition: variable.c:1590
st_index_t rb_ivar_count(VALUE obj)
Definition: variable.c:1511
void * rb_mod_const_at(VALUE mod, void *data)
Definition: variable.c:2563
VALUE rb_cv_get(VALUE klass, const char *name)
Definition: variable.c:3149
VALUE rb_const_source_location(VALUE klass, ID id)
Definition: variable.c:2461
VALUE rb_const_missing(VALUE klass, VALUE name)
Definition: variable.c:1694
VALUE rb_class_name(VALUE klass)
Definition: variable.c:274
void rb_cv_set(VALUE klass, const char *name, VALUE val)
Definition: variable.c:3142
VALUE rb_class_path(VALUE klass)
Definition: variable.c:153
MJIT_FUNC_EXPORTED VALUE rb_public_const_get_at(VALUE klass, ID id)
Definition: variable.c:2409
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
Definition: variable.c:3248
#define check_autoload_table(av)
Definition: variable.c:1783
VALUE rb_f_global_variables(void)
Definition: variable.c:728
VALUE rb_attr_get(VALUE obj, ID id)
Definition: variable.c:1084
VALUE rb_mod_const_missing(VALUE klass, VALUE name)
Definition: variable.c:1739
void rb_gvar_var_setter(VALUE val, ID id, VALUE *data)
Definition: variable.c:400
int rb_const_defined_at(VALUE klass, ID id)
Definition: variable.c:2692
int rb_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2680
VALUE rb_gvar_var_getter(ID id, VALUE *var)
Definition: variable.c:393
void * rb_mod_const_of(VALUE mod, void *data)
Definition: variable.c:2576
VALUE rb_mod_remove_const(VALUE mod, VALUE name)
Definition: variable.c:2483
RUBY_FUNC_EXPORTED void rb_autoload(VALUE mod, ID id, const char *file)
Definition: variable.c:1928
void rb_define_class_variable(VALUE klass, const char *name, VALUE val)
Definition: variable.c:3156
VALUE rb_ivar_defined(VALUE obj, ID id)
Definition: variable.c:1317
VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
Definition: variable.c:3022
void rb_free_generic_ivar(VALUE obj)
Definition: variable.c:993
VALUE rb_vm_top_self(void)
Definition: vm.c:3349
#define rb_id2str(id)
Definition: vm_backtrace.c:30