Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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