Ruby 4.0.7p0 (2026-09-15 revision 229531a6cfbf07e3caef30dbac24a2a3f3fed482)
vm_core.h
1#ifndef RUBY_VM_CORE_H
2#define RUBY_VM_CORE_H
3/**********************************************************************
4
5 vm_core.h -
6
7 $Author$
8 created at: 04/01/01 19:41:38 JST
9
10 Copyright (C) 2004-2007 Koichi Sasada
11
12**********************************************************************/
13
14/*
15 * Enable check mode.
16 * 1: enable local assertions.
17 */
18#ifndef VM_CHECK_MODE
19
20// respect RUBY_DUBUG: if given n is 0, then use RUBY_DEBUG
21#define N_OR_RUBY_DEBUG(n) (((n) > 0) ? (n) : RUBY_DEBUG)
22
23#define VM_CHECK_MODE N_OR_RUBY_DEBUG(0)
24#endif
25
38
39#ifndef VMDEBUG
40#define VMDEBUG 0
41#endif
42
43#if 0
44#undef VMDEBUG
45#define VMDEBUG 3
46#endif
47
48#include "ruby/internal/config.h"
49
50#include <stddef.h>
51#include <signal.h>
52#include <stdarg.h>
53
54#include "ruby_assert.h"
55
56#define RVALUE_SIZE (sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]))
57
58#if VM_CHECK_MODE > 0
59#define VM_ASSERT(expr, ...) \
60 RUBY_ASSERT_MESG_WHEN(VM_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
61#define VM_UNREACHABLE(func) rb_bug(#func ": unreachable")
62#define RUBY_ASSERT_CRITICAL_SECTION
63#define RUBY_DEBUG_THREAD_SCHEDULE() rb_thread_schedule()
64#else
65#define VM_ASSERT(/*expr, */...) ((void)0)
66#define VM_UNREACHABLE(func) UNREACHABLE
67#define RUBY_DEBUG_THREAD_SCHEDULE()
68#endif
69
70#define RUBY_ASSERT_MUTEX_OWNED(mutex) VM_ASSERT(rb_mutex_owned_p(mutex))
71
72#if defined(RUBY_ASSERT_CRITICAL_SECTION)
73/*
74# Critical Section Assertions
75
76These assertions are used to ensure that context switching does not occur between two points in the code. In theory,
77such code should already be protected by a mutex, but these assertions are used to ensure that the mutex is held.
78
79The specific case where it can be useful is where a mutex is held further up the call stack, and the code in question
80may not directly hold the mutex. In this case, the critical section assertions can be used to ensure that the mutex is
81held by someone else.
82
83These assertions are only enabled when RUBY_ASSERT_CRITICAL_SECTION is defined, which is only defined if VM_CHECK_MODE
84is set.
85
86## Example Usage
87
88```c
89RUBY_ASSERT_CRITICAL_SECTION_ENTER();
90// ... some code which does not invoke rb_vm_check_ints() ...
91RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
92```
93
94If `rb_vm_check_ints()` is called between the `RUBY_ASSERT_CRITICAL_SECTION_ENTER()` and
95`RUBY_ASSERT_CRITICAL_SECTION_LEAVE()`, a failed assertion will result.
96*/
97extern int ruby_assert_critical_section_entered;
98#define RUBY_ASSERT_CRITICAL_SECTION_ENTER() do{ruby_assert_critical_section_entered += 1;}while(false)
99#define RUBY_ASSERT_CRITICAL_SECTION_LEAVE() do{VM_ASSERT(ruby_assert_critical_section_entered > 0);ruby_assert_critical_section_entered -= 1;}while(false)
100#else
101#define RUBY_ASSERT_CRITICAL_SECTION_ENTER()
102#define RUBY_ASSERT_CRITICAL_SECTION_LEAVE()
103#endif
104
105#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
106# include "wasm/setjmp.h"
107#else
108# include <setjmp.h>
109#endif
110
111#if defined(__linux__) || defined(__FreeBSD__)
112# define RB_THREAD_T_HAS_NATIVE_ID
113#endif
114
116#include "ccan/list/list.h"
117#include "id.h"
118#include "internal.h"
119#include "internal/array.h"
120#include "internal/basic_operators.h"
121#include "internal/box.h"
122#include "internal/sanitizers.h"
123#include "internal/serial.h"
124#include "internal/set_table.h"
125#include "internal/vm.h"
126#include "method.h"
127#include "node.h"
128#include "ruby/ruby.h"
129#include "ruby/st.h"
130#include "ruby_atomic.h"
131#include "vm_opts.h"
132
133#include "ruby/thread_native.h"
134/*
135 * implementation selector of get_insn_info algorithm
136 * 0: linear search
137 * 1: binary search
138 * 2: succinct bitvector
139 */
140#ifndef VM_INSN_INFO_TABLE_IMPL
141# define VM_INSN_INFO_TABLE_IMPL 2
142#endif
143
144#if defined(NSIG_MAX) /* POSIX issue 8 */
145# undef NSIG
146# define NSIG NSIG_MAX
147#elif defined(_SIG_MAXSIG) /* FreeBSD */
148# undef NSIG
149# define NSIG _SIG_MAXSIG
150#elif defined(_SIGMAX) /* QNX */
151# define NSIG (_SIGMAX + 1)
152#elif defined(NSIG) /* 99% of everything else */
153# /* take it */
154#else /* Last resort */
155# define NSIG (sizeof(sigset_t) * CHAR_BIT + 1)
156#endif
157
158#define RUBY_NSIG NSIG
159
160#if defined(SIGCLD)
161# define RUBY_SIGCHLD (SIGCLD)
162#elif defined(SIGCHLD)
163# define RUBY_SIGCHLD (SIGCHLD)
164#endif
165
166#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__)
167# define USE_SIGALTSTACK
168void *rb_allocate_sigaltstack(void);
169void *rb_register_sigaltstack(void *);
170# define RB_ALTSTACK_INIT(var, altstack) var = rb_register_sigaltstack(altstack)
171# define RB_ALTSTACK_FREE(var) free(var)
172# define RB_ALTSTACK(var) var
173#else /* noop */
174# define RB_ALTSTACK_INIT(var, altstack)
175# define RB_ALTSTACK_FREE(var)
176# define RB_ALTSTACK(var) (0)
177#endif
178
179#include THREAD_IMPL_H
180#define RUBY_VM_THREAD_MODEL 2
181
182/*****************/
183/* configuration */
184/*****************/
185
186/* gcc ver. check */
187#if defined(__GNUC__) && __GNUC__ >= 2
188
189#if OPT_TOKEN_THREADED_CODE
190#if OPT_DIRECT_THREADED_CODE
191#undef OPT_DIRECT_THREADED_CODE
192#endif
193#endif
194
195#else /* defined(__GNUC__) && __GNUC__ >= 2 */
196
197/* disable threaded code options */
198#if OPT_DIRECT_THREADED_CODE
199#undef OPT_DIRECT_THREADED_CODE
200#endif
201#if OPT_TOKEN_THREADED_CODE
202#undef OPT_TOKEN_THREADED_CODE
203#endif
204#endif
205
206/* call threaded code */
207#if OPT_CALL_THREADED_CODE
208#if OPT_DIRECT_THREADED_CODE
209#undef OPT_DIRECT_THREADED_CODE
210#endif /* OPT_DIRECT_THREADED_CODE */
211#endif /* OPT_CALL_THREADED_CODE */
212
213void rb_vm_encoded_insn_data_table_init(void);
214typedef unsigned long rb_num_t;
215typedef signed long rb_snum_t;
216
217enum ruby_tag_type {
218 RUBY_TAG_NONE = 0x0,
219 RUBY_TAG_RETURN = 0x1,
220 RUBY_TAG_BREAK = 0x2,
221 RUBY_TAG_NEXT = 0x3,
222 RUBY_TAG_RETRY = 0x4,
223 RUBY_TAG_REDO = 0x5,
224 RUBY_TAG_RAISE = 0x6,
225 RUBY_TAG_THROW = 0x7,
226 RUBY_TAG_FATAL = 0x8,
227 RUBY_TAG_MASK = 0xf
228};
229
230#define TAG_NONE RUBY_TAG_NONE
231#define TAG_RETURN RUBY_TAG_RETURN
232#define TAG_BREAK RUBY_TAG_BREAK
233#define TAG_NEXT RUBY_TAG_NEXT
234#define TAG_RETRY RUBY_TAG_RETRY
235#define TAG_REDO RUBY_TAG_REDO
236#define TAG_RAISE RUBY_TAG_RAISE
237#define TAG_THROW RUBY_TAG_THROW
238#define TAG_FATAL RUBY_TAG_FATAL
239#define TAG_MASK RUBY_TAG_MASK
240
241enum ruby_vm_throw_flags {
242 VM_THROW_NO_ESCAPE_FLAG = 0x8000,
243 VM_THROW_STATE_MASK = 0xff
244};
245
246/* forward declarations */
247struct rb_thread_struct;
249
250/* iseq data type */
251typedef struct rb_compile_option_struct rb_compile_option_t;
252
254 rb_serial_t raw;
255 VALUE data[2];
256};
257
258#define IMEMO_CONST_CACHE_SHAREABLE IMEMO_FL_USER0
259
260// imemo_constcache
262 VALUE flags;
263
264 VALUE value;
265 const rb_cref_t *ic_cref;
266};
267STATIC_ASSERT(sizeof_iseq_inline_constant_cache_entry,
268 (offsetof(struct iseq_inline_constant_cache_entry, ic_cref) +
269 sizeof(const rb_cref_t *)) <= RVALUE_SIZE);
270
287
289 uint64_t value; // dest_shape_id in former half, attr_index in latter half
290 ID iv_set_name;
291};
292
296
298 struct {
299 struct rb_thread_struct *running_thread;
300 VALUE value;
301 } once;
302 struct iseq_inline_constant_cache ic_cache;
303 struct iseq_inline_iv_cache_entry iv_cache;
304};
305
307 const struct rb_call_data *cd;
308 const struct rb_callcache *cc;
309 VALUE block_handler;
310 VALUE recv;
311 int argc;
312 bool kw_splat;
313 VALUE heap_argv;
314};
315
316#ifndef VM_ARGC_STACK_MAX
317#define VM_ARGC_STACK_MAX 128
318#endif
319
320#define VM_KW_SPECIFIED_BITS_MAX (32-1) /* TODO: 32 -> Fixnum's max bits */
321
322# define CALLING_ARGC(calling) ((calling)->heap_argv ? RARRAY_LENINT((calling)->heap_argv) : (calling)->argc)
323
325
326#if 1
327#define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj)
328#else
329#define CoreDataFromValue(obj, type) (type*)rb_data_object_get(obj)
330#endif
331#define GetCoreDataFromValue(obj, type, ptr) ((ptr) = CoreDataFromValue((obj), type))
332
334 VALUE pathobj; /* String (path) or Array [path, realpath]. Frozen. */
335 VALUE base_label; /* String */
336 VALUE label; /* String */
337 int first_lineno;
338 int node_id;
339 rb_code_location_t code_location;
340} rb_iseq_location_t;
341
342#define PATHOBJ_PATH 0
343#define PATHOBJ_REALPATH 1
344
345static inline VALUE
346pathobj_path(VALUE pathobj)
347{
348 if (RB_TYPE_P(pathobj, T_STRING)) {
349 return pathobj;
350 }
351 else {
352 VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY));
353 return RARRAY_AREF(pathobj, PATHOBJ_PATH);
354 }
355}
356
357static inline VALUE
358pathobj_realpath(VALUE pathobj)
359{
360 if (RB_TYPE_P(pathobj, T_STRING)) {
361 return pathobj;
362 }
363 else {
364 VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY));
365 return RARRAY_AREF(pathobj, PATHOBJ_REALPATH);
366 }
367}
368
369/* Forward declarations */
370typedef uintptr_t iseq_bits_t;
371
372#define ISEQ_IS_SIZE(body) (body->ic_size + body->ivc_size + body->ise_size + body->icvarc_size)
373
374/* [ TS_IVC | TS_ICVARC | TS_ISE | TS_IC ] */
375#define ISEQ_IS_IC_ENTRY(body, idx) (body->is_entries[(idx) + body->ise_size + body->icvarc_size + body->ivc_size].ic_cache);
376
377/* instruction sequence type */
378enum rb_iseq_type {
379 ISEQ_TYPE_TOP,
380 ISEQ_TYPE_METHOD,
381 ISEQ_TYPE_BLOCK,
382 ISEQ_TYPE_CLASS,
383 ISEQ_TYPE_RESCUE,
384 ISEQ_TYPE_ENSURE,
385 ISEQ_TYPE_EVAL,
386 ISEQ_TYPE_MAIN,
387 ISEQ_TYPE_PLAIN
388};
389
390// Attributes specified by Primitive.attr!
391enum rb_builtin_attr {
392 // The iseq does not call methods.
393 BUILTIN_ATTR_LEAF = 0x01,
394 // This iseq only contains single `opt_invokebuiltin_delegate_leave` instruction with 0 arguments.
395 BUILTIN_ATTR_SINGLE_NOARG_LEAF = 0x02,
396 // This attribute signals JIT to duplicate the iseq for each block iseq so that its `yield` will be monomorphic.
397 BUILTIN_ATTR_INLINE_BLOCK = 0x04,
398 // The iseq acts like a C method in backtraces.
399 BUILTIN_ATTR_C_TRACE = 0x08,
400};
401
402typedef VALUE (*rb_jit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *);
403typedef VALUE (*rb_zjit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *, rb_jit_func_t);
404
406 enum rb_iseq_type type;
407
408 unsigned int iseq_size;
409 VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */
410
433
435 struct {
436 unsigned int has_lead : 1;
437 unsigned int has_opt : 1;
438 unsigned int has_rest : 1;
439 unsigned int has_post : 1;
440 unsigned int has_kw : 1;
441 unsigned int has_kwrest : 1;
442 unsigned int has_block : 1;
443
444 unsigned int ambiguous_param0 : 1; /* {|a|} */
445 unsigned int accepts_no_kwarg : 1;
446 unsigned int ruby2_keywords: 1;
447 unsigned int anon_rest: 1;
448 unsigned int anon_kwrest: 1;
449 unsigned int use_block: 1;
450 unsigned int forwardable: 1;
451 } flags;
452
453 unsigned int size;
454
455 int lead_num;
456 int opt_num;
457 int rest_start;
458 int post_start;
459 int post_num;
460 int block_start;
461
462 const VALUE *opt_table; /* (opt_num + 1) entries. */
463 /* opt_num and opt_table:
464 *
465 * def foo o1=e1, o2=e2, ..., oN=eN
466 * #=>
467 * # prologue code
468 * A1: e1
469 * A2: e2
470 * ...
471 * AN: eN
472 * AL: body
473 * opt_num = N
474 * opt_table = [A1, A2, ..., AN, AL]
475 */
476
478 int num;
479 int required_num;
480 int bits_start;
481 int rest_start;
482 const ID *table;
483 VALUE *default_values;
484 } *keyword;
485 } param;
486
487 rb_iseq_location_t location;
488
489 /* insn info, must be freed */
491 const struct iseq_insn_info_entry *body;
492 unsigned int *positions;
493 unsigned int size;
494#if VM_INSN_INFO_TABLE_IMPL == 2
495 struct succ_index_table *succ_index_table;
496#endif
497 } insns_info;
498
499 const ID *local_table; /* must free */
500
501 enum lvar_state {
502 lvar_uninitialized,
503 lvar_initialized,
504 lvar_reassigned,
505 } *lvar_states;
506
507 /* catch table */
508 struct iseq_catch_table *catch_table;
509
510 /* for child iseq */
511 const struct rb_iseq_struct *parent_iseq;
512 struct rb_iseq_struct *local_iseq; /* local_iseq->flip_cnt can be modified */
513
514 union iseq_inline_storage_entry *is_entries; /* [ TS_IVC | TS_ICVARC | TS_ISE | TS_IC ] */
515 struct rb_call_data *call_data; //struct rb_call_data calls[ci_size];
516
517 struct {
518 rb_snum_t flip_count;
519 VALUE script_lines;
520 VALUE coverage;
521 VALUE pc2branchindex;
522 VALUE *original_iseq;
523 } variable;
524
525 unsigned int local_table_size;
526 unsigned int ic_size; // Number of IC caches
527 unsigned int ise_size; // Number of ISE caches
528 unsigned int ivc_size; // Number of IVC caches
529 unsigned int icvarc_size; // Number of ICVARC caches
530 unsigned int ci_size;
531 unsigned int stack_max; /* for stack overflow check */
532
533 unsigned int builtin_attrs; // Union of rb_builtin_attr
534
535 bool prism; // ISEQ was generated from prism compiler
536
537 // Set once an EP escape of this iseq has been reported to the enabled JIT.
538 rb_atomic_t jit_ep_escape_recorded;
539
540 union {
541 iseq_bits_t * list; /* Find references for GC */
542 iseq_bits_t single;
543 } mark_bits;
544
545 struct rb_id_table *outer_variables;
546
547 const rb_iseq_t *mandatory_only_iseq;
548
549#if USE_YJIT || USE_ZJIT
550 // Function pointer for JIT code on jit_exec()
551 rb_jit_func_t jit_entry;
552 // Number of calls on jit_exec()
553 long unsigned jit_entry_calls;
554 // Function pointer for JIT code on jit_exec_exception()
555 rb_jit_func_t jit_exception;
556 // Number of calls on jit_exec_exception()
557 long unsigned jit_exception_calls;
558#endif
559
560#if USE_YJIT
561 // YJIT stores some data on each iseq.
562 void *yjit_payload;
563 // Used to estimate how frequently this ISEQ gets called
564 uint64_t yjit_calls_at_interv;
565#endif
566
567#if USE_ZJIT
568 // ZJIT stores some data on each iseq.
569 void *zjit_payload;
570#endif
571};
572
573/* T_IMEMO/iseq */
574/* typedef rb_iseq_t is in method.h */
576 VALUE flags; /* 1 */
577 VALUE wrapper; /* 2 */
578
579 struct rb_iseq_constant_body *body; /* 3 */
580
581 union { /* 4, 5 words */
582 struct iseq_compile_data *compile_data; /* used at compile time */
583
584 struct {
585 VALUE obj;
586 int index;
587 } loader;
588
589 struct {
590 unsigned int local_hooks_cnt;
591 rb_event_flag_t global_trace_events;
592 } exec;
593 } aux;
594};
595
596#define ISEQ_BODY(iseq) ((iseq)->body)
597
598#if !defined(USE_LAZY_LOAD) || !(USE_LAZY_LOAD+0)
599#define USE_LAZY_LOAD 0
600#endif
601
602#if !USE_LAZY_LOAD
603static inline const rb_iseq_t *rb_iseq_complete(const rb_iseq_t *iseq) {return 0;}
604#endif
605const rb_iseq_t *rb_iseq_complete(const rb_iseq_t *iseq);
606
607static inline const rb_iseq_t *
608rb_iseq_check(const rb_iseq_t *iseq)
609{
610 if (USE_LAZY_LOAD && ISEQ_BODY(iseq) == NULL) {
611 rb_iseq_complete((rb_iseq_t *)iseq);
612 }
613 return iseq;
614}
615
616static inline bool
617rb_iseq_attr_p(const rb_iseq_t *iseq, enum rb_builtin_attr attr)
618{
619 return (ISEQ_BODY(iseq)->builtin_attrs & attr) == attr;
620}
621
622static inline const rb_iseq_t *
623def_iseq_ptr(rb_method_definition_t *def)
624{
625//TODO: re-visit. to check the bug, enable this assertion.
626#if VM_CHECK_MODE > 0
627 if (def->type != VM_METHOD_TYPE_ISEQ) rb_bug("def_iseq_ptr: not iseq (%d)", def->type);
628#endif
629 return rb_iseq_check(def->body.iseq.iseqptr);
630}
631
632enum ruby_special_exceptions {
633 ruby_error_reenter,
634 ruby_error_nomemory,
635 ruby_error_sysstack,
636 ruby_error_stackfatal,
637 ruby_error_stream_closed,
638 ruby_special_error_count
639};
640
641#define GetVMPtr(obj, ptr) \
642 GetCoreDataFromValue((obj), rb_vm_t, (ptr))
643
644struct rb_vm_struct;
645typedef void rb_vm_at_exit_func(struct rb_vm_struct*);
646
647typedef struct rb_at_exit_list {
648 rb_vm_at_exit_func *func;
649 struct rb_at_exit_list *next;
651
652void *rb_objspace_alloc(void);
653void rb_objspace_free(void *objspace);
654void rb_objspace_call_finalizer(void);
655
656enum rb_hook_list_type {
657 hook_list_type_ractor_local,
658 hook_list_type_targeted_iseq,
659 hook_list_type_targeted_def, // C function
660 hook_list_type_global
661};
662
663typedef struct rb_hook_list_struct {
664 struct rb_event_hook_struct *hooks;
665 rb_event_flag_t events;
666 unsigned int running;
667 enum rb_hook_list_type type;
668 bool need_clean;
669} rb_hook_list_t;
670
671// see builtin.h for definition
672typedef const struct rb_builtin_function *RB_BUILTIN;
673
675 VALUE *varptr;
676 struct global_object_list *next;
677};
678
679typedef struct rb_vm_struct {
680 VALUE self;
681
682 struct {
683 struct ccan_list_head set;
684 unsigned int cnt;
685 unsigned int blocking_cnt;
686
687 struct rb_ractor_struct *main_ractor;
688 struct rb_thread_struct *main_thread; // == vm->ractor.main_ractor->threads.main
689
690 struct {
691 // monitor
692 rb_nativethread_lock_t lock;
693 struct rb_ractor_struct *lock_owner;
694 unsigned int lock_rec;
695
696 // join at exit
697 rb_nativethread_cond_t terminate_cond;
698 bool terminate_waiting;
699
700#ifndef RUBY_THREAD_PTHREAD_H
701 // win32
702 bool barrier_waiting;
703 unsigned int barrier_cnt;
704 rb_nativethread_cond_t barrier_complete_cond;
705 rb_nativethread_cond_t barrier_release_cond;
706#endif
707 } sync;
708
709#ifdef RUBY_THREAD_PTHREAD_H
710 // ractor scheduling
711 struct {
712 rb_nativethread_lock_t lock;
713 struct rb_ractor_struct *lock_owner;
714 bool locked;
715
716 rb_nativethread_cond_t cond; // GRQ
717 unsigned int snt_cnt; // count of shared NTs
718 unsigned int dnt_cnt; // count of dedicated NTs
719
720 unsigned int running_cnt;
721
722 unsigned int max_cpu;
723 struct ccan_list_head grq; // // Global Ready Queue
724 unsigned int grq_cnt;
725
726 // running threads
727 struct ccan_list_head running_threads;
728
729 // threads which switch context by timeslice
730 struct ccan_list_head timeslice_threads;
731
732 struct ccan_list_head zombie_threads;
733
734 // true if timeslice timer is not enable
735 bool timeslice_wait_inf;
736
737 // barrier
738 rb_nativethread_cond_t barrier_complete_cond;
739 rb_nativethread_cond_t barrier_release_cond;
740 bool barrier_waiting;
741 unsigned int barrier_waiting_cnt;
742 unsigned int barrier_serial;
743 struct rb_ractor_struct *barrier_ractor;
744 unsigned int barrier_lock_rec;
745 } sched;
746#endif
747 } ractor;
748
749#ifdef USE_SIGALTSTACK
750 void *main_altstack;
751#endif
752
753 rb_serial_t fork_gen;
754
755 /* set in single-threaded processes only: */
756 volatile int ubf_async_safe;
757
758 unsigned int running: 1;
759 unsigned int thread_abort_on_exception: 1;
760 unsigned int thread_report_on_exception: 1;
761 unsigned int thread_ignore_deadlock: 1;
762
763 /* object management */
764 VALUE mark_object_ary;
766 const VALUE special_exceptions[ruby_special_error_count];
767
768 /* Ruby Box */
769 rb_box_t *master_box;
770 rb_box_t *root_box;
771 rb_box_t *main_box;
772
773 /* load */
774 // For running the init function of statically linked
775 // extensions when they are loaded
776 struct st_table *static_ext_inits;
777
778 /* signal */
779 struct {
780 VALUE cmd[RUBY_NSIG];
781 } trap_list;
782
783 /* hook (for internal events: NEWOBJ, FREEOBJ, GC events, etc.) */
784 rb_hook_list_t global_hooks;
785
786 /* postponed_job (async-signal-safe, and thread-safe) */
787 struct rb_postponed_job_queue *postponed_job_queue;
788
789 int src_encoding_index;
790
791 /* workqueue (thread-safe, NOT async-signal-safe) */
792 struct ccan_list_head workqueue; /* <=> rb_workqueue_job.jnode */
793 rb_nativethread_lock_t workqueue_lock;
794
795 VALUE orig_progname, progname;
796 VALUE coverages, me2counter;
797 int coverage_mode;
798
799 struct {
800 struct rb_objspace *objspace;
801 struct gc_mark_func_data_struct {
802 void *data;
803 void (*mark_func)(VALUE v, void *data);
804 } *mark_func_data;
805 } gc;
806
807 rb_at_exit_list *at_exit;
808
809 const struct rb_builtin_function *builtin_function_table;
810
811 st_table *ci_table;
812 struct rb_id_table *negative_cme_table;
813 st_table *overloaded_cme_table; // cme -> overloaded_cme
814 set_table *unused_block_warning_table;
815 set_table *cc_refinement_table;
816
817 // This id table contains a mapping from ID to ICs. It does this with ID
818 // keys and nested st_tables as values. The nested tables have ICs as keys
819 // and Qtrue as values. It is used when inline constant caches need to be
820 // invalidated or ISEQs are being freed.
821 struct rb_id_table *constant_cache;
822 ID inserting_constant_cache_id;
823
824#ifndef VM_GLOBAL_CC_CACHE_TABLE_SIZE
825#define VM_GLOBAL_CC_CACHE_TABLE_SIZE 1023
826#endif
827 const struct rb_callcache *global_cc_cache_table[VM_GLOBAL_CC_CACHE_TABLE_SIZE]; // vm_eval.c
828
829#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
830 uint32_t clock;
831#endif
832
833 /* params */
834 struct { /* size in byte */
835 size_t thread_vm_stack_size;
836 size_t thread_machine_stack_size;
837 size_t fiber_vm_stack_size;
838 size_t fiber_machine_stack_size;
839 } default_params;
840} rb_vm_t;
841
842extern bool ruby_vm_during_cleanup;
843
844/* default values */
845
846#define RUBY_VM_SIZE_ALIGN 4096
847
848#define RUBY_VM_THREAD_VM_STACK_SIZE ( 128 * 1024 * sizeof(VALUE)) /* 512 KB or 1024 KB */
849#define RUBY_VM_THREAD_VM_STACK_SIZE_MIN ( 2 * 1024 * sizeof(VALUE)) /* 8 KB or 16 KB */
850#define RUBY_VM_THREAD_MACHINE_STACK_SIZE ( 128 * 1024 * sizeof(VALUE)) /* 512 KB or 1024 KB */
851#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
852
853#define RUBY_VM_FIBER_VM_STACK_SIZE ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
854#define RUBY_VM_FIBER_VM_STACK_SIZE_MIN ( 2 * 1024 * sizeof(VALUE)) /* 8 KB or 16 KB */
855#define RUBY_VM_FIBER_MACHINE_STACK_SIZE ( 64 * 1024 * sizeof(VALUE)) /* 256 KB or 512 KB */
856#if defined(__powerpc64__) || defined(__ppc64__) // macOS has __ppc64__
857#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 32 * 1024 * sizeof(VALUE)) /* 128 KB or 256 KB */
858#else
859#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
860#endif
861
862#if __has_feature(memory_sanitizer) || __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)
863/* It seems sanitizers consume A LOT of machine stacks */
864#undef RUBY_VM_THREAD_MACHINE_STACK_SIZE
865#define RUBY_VM_THREAD_MACHINE_STACK_SIZE (1024 * 1024 * sizeof(VALUE))
866#undef RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
867#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN ( 512 * 1024 * sizeof(VALUE))
868#undef RUBY_VM_FIBER_MACHINE_STACK_SIZE
869#define RUBY_VM_FIBER_MACHINE_STACK_SIZE ( 256 * 1024 * sizeof(VALUE))
870#undef RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
871#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 128 * 1024 * sizeof(VALUE))
872#endif
873
874#ifndef VM_DEBUG_BP_CHECK
875#define VM_DEBUG_BP_CHECK 0
876#endif
877
878#ifndef VM_DEBUG_VERIFY_METHOD_CACHE
879#define VM_DEBUG_VERIFY_METHOD_CACHE (VMDEBUG != 0)
880#endif
881
883 VALUE self;
884 const VALUE *ep;
885 union {
886 const rb_iseq_t *iseq;
887 const struct vm_ifunc *ifunc;
888 VALUE val;
889 } code;
890};
891
892enum rb_block_handler_type {
893 block_handler_type_iseq,
894 block_handler_type_ifunc,
895 block_handler_type_symbol,
896 block_handler_type_proc
897};
898
899enum rb_block_type {
900 block_type_iseq,
901 block_type_ifunc,
902 block_type_symbol,
903 block_type_proc
904};
905
906struct rb_block {
907 union {
908 struct rb_captured_block captured;
909 VALUE symbol;
910 VALUE proc;
911 } as;
912 enum rb_block_type type;
913};
914
916 const VALUE *pc; // cfp[0]
917 VALUE *sp; // cfp[1]
918 const rb_iseq_t *iseq; // cfp[2]
919 VALUE self; // cfp[3] / block[0]
920 const VALUE *ep; // cfp[4] / block[1]
921 const void *block_code; // cfp[5] / block[2] -- iseq, ifunc, or forwarded block handler
922 void *jit_return; // cfp[6] -- return address for JIT code
923#if VM_DEBUG_BP_CHECK
924 VALUE *bp_check; // cfp[7]
925#endif
926} rb_control_frame_t;
927
928extern const rb_data_type_t ruby_threadptr_data_type;
929
930static inline struct rb_thread_struct *
931rb_thread_ptr(VALUE thval)
932{
933 return (struct rb_thread_struct *)rb_check_typeddata(thval, &ruby_threadptr_data_type);
934}
935
936enum rb_thread_status {
937 THREAD_RUNNABLE,
938 THREAD_STOPPED,
939 THREAD_STOPPED_FOREVER,
940 THREAD_KILLED
941};
942
943#ifdef RUBY_JMP_BUF
944typedef RUBY_JMP_BUF rb_jmpbuf_t;
945#else
946typedef void *rb_jmpbuf_t[5];
947#endif
948
949/*
950 `rb_vm_tag_jmpbuf_t` type represents a buffer used to
951 long jump to a C frame associated with `rb_vm_tag`.
952
953 Use-site of `rb_vm_tag_jmpbuf_t` is responsible for calling the
954 following functions:
955 - `rb_vm_tag_jmpbuf_init` once `rb_vm_tag_jmpbuf_t` is allocated.
956 - `rb_vm_tag_jmpbuf_deinit` once `rb_vm_tag_jmpbuf_t` is no longer necessary.
957
958 `RB_VM_TAG_JMPBUF_GET` transforms a `rb_vm_tag_jmpbuf_t` into a
959 `rb_jmpbuf_t` to be passed to `rb_setjmp/rb_longjmp`.
960*/
961#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
962/*
963 WebAssembly target with Asyncify-based SJLJ needs
964 to capture the execution context by unwind/rewind-ing
965 call frames into a jump buffer. The buffer space tends
966 to be considerably large unlike other architectures'
967 register-based buffers.
968 Therefore, we allocates the buffer on the heap on such
969 environments.
970*/
971typedef rb_jmpbuf_t *rb_vm_tag_jmpbuf_t;
972
973#define RB_VM_TAG_JMPBUF_GET(buf) (*buf)
974
975static inline void
976rb_vm_tag_jmpbuf_init(rb_vm_tag_jmpbuf_t *jmpbuf)
977{
978 *jmpbuf = ruby_xmalloc(sizeof(rb_jmpbuf_t));
979}
980
981static inline void
982rb_vm_tag_jmpbuf_deinit(const rb_vm_tag_jmpbuf_t *jmpbuf)
983{
984 ruby_xfree(*jmpbuf);
985}
986#else
987typedef rb_jmpbuf_t rb_vm_tag_jmpbuf_t;
988
989#define RB_VM_TAG_JMPBUF_GET(buf) (buf)
990
991static inline void
992rb_vm_tag_jmpbuf_init(rb_vm_tag_jmpbuf_t *jmpbuf)
993{
994 // no-op
995}
996
997static inline void
998rb_vm_tag_jmpbuf_deinit(const rb_vm_tag_jmpbuf_t *jmpbuf)
999{
1000 // no-op
1001}
1002#endif
1003
1004/*
1005 the members which are written in EC_PUSH_TAG() should be placed at
1006 the beginning and the end, so that entire region is accessible.
1007*/
1009 VALUE tag;
1010 VALUE retval;
1011 rb_vm_tag_jmpbuf_t buf;
1012 struct rb_vm_tag *prev;
1013 enum ruby_tag_type state;
1014 unsigned int lock_rec;
1015};
1016
1017STATIC_ASSERT(rb_vm_tag_buf_offset, offsetof(struct rb_vm_tag, buf) > 0);
1018STATIC_ASSERT(rb_vm_tag_buf_end,
1019 offsetof(struct rb_vm_tag, buf) + sizeof(rb_vm_tag_jmpbuf_t) <
1020 sizeof(struct rb_vm_tag));
1021
1024 void *arg;
1025};
1026
1027struct rb_mutex_struct;
1028
1029typedef struct rb_fiber_struct rb_fiber_t;
1030
1032 struct rb_waiting_list *next;
1033 struct rb_thread_struct *thread;
1034 struct rb_fiber_struct *fiber;
1035};
1036
1038 /* execution information */
1039 VALUE *vm_stack; /* must free, must mark */
1040 size_t vm_stack_size; /* size in word (byte size / sizeof(VALUE)) */
1041 rb_control_frame_t *cfp;
1042
1043 struct rb_vm_tag *tag;
1044
1045 /* interrupt flags */
1046 rb_atomic_t interrupt_flag;
1047 rb_atomic_t interrupt_mask; /* size should match flag */
1048#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
1049 uint32_t checked_clock;
1050#endif
1051
1052 rb_fiber_t *fiber_ptr;
1053 struct rb_thread_struct *thread_ptr;
1054 rb_serial_t serial;
1055 rb_serial_t ractor_id;
1056
1057 /* storage (ec (fiber) local) */
1058 struct rb_id_table *local_storage;
1059 VALUE local_storage_recursive_hash;
1060 VALUE local_storage_recursive_hash_for_trace;
1061
1062 /* Inheritable fiber storage. */
1063 VALUE storage;
1064
1065 /* eval env */
1066 const VALUE *root_lep;
1067 VALUE root_svar;
1068
1069 /* trace information */
1070 struct rb_trace_arg_struct *trace_arg;
1071
1072 /* temporary places */
1073 VALUE errinfo;
1074 VALUE passed_block_handler; /* for rb_iterate */
1075
1076 uint8_t raised_flag; /* only 3 bits needed */
1077
1078 /* n.b. only 7 bits needed, really: */
1079 BITFIELD(enum method_missing_reason, method_missing_reason, 8);
1080
1081 VALUE private_const_reference;
1082
1083 struct {
1084 VALUE obj;
1085 VALUE fields_obj;
1086 } gen_fields_cache;
1087
1088 /* for GC */
1089 struct {
1090 VALUE *stack_start;
1091 VALUE *stack_end;
1092 size_t stack_maxsize;
1093 RUBY_ALIGNAS(SIZEOF_VALUE) jmp_buf regs;
1094
1095#ifdef RUBY_ASAN_ENABLED
1096 void *asan_fake_stack_handle;
1097#endif
1098 } machine;
1099};
1100
1101#ifndef rb_execution_context_t
1102typedef struct rb_execution_context_struct rb_execution_context_t;
1103#define rb_execution_context_t rb_execution_context_t
1104#endif
1105
1106// for builtin.h
1107#define VM_CORE_H_EC_DEFINED 1
1108
1109// Set the vm_stack pointer in the execution context.
1110void rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
1111
1112// Initialize the vm_stack pointer in the execution context and push the initial stack frame.
1113// @param ec the execution context to update.
1114// @param stack a pointer to the stack to use.
1115// @param size the size of the stack, as in `VALUE stack[size]`.
1116void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
1117
1118// Clear (set to `NULL`) the vm_stack pointer.
1119// @param ec the execution context to update.
1120void rb_ec_clear_vm_stack(rb_execution_context_t *ec);
1121
1122// Close an execution context and free related resources that are no longer needed.
1123// @param ec the execution context to close.
1124void rb_ec_close(rb_execution_context_t *ec);
1125
1127 bool ractor_safe;
1128};
1129
1130typedef struct rb_ractor_struct rb_ractor_t;
1131
1132struct rb_native_thread;
1133
1134typedef struct rb_thread_struct {
1135 struct ccan_list_node lt_node; // managed by a ractor (r->threads.set)
1136 VALUE self;
1137 rb_ractor_t *ractor;
1138 rb_vm_t *vm;
1139 struct rb_native_thread *nt;
1140 rb_execution_context_t *ec;
1141
1142 struct rb_thread_sched_item sched;
1143 bool mn_schedulable;
1144 rb_atomic_t serial; // only for RUBY_DEBUG_LOG()
1145
1146 VALUE last_status; /* $? */
1147
1148 /* for cfunc */
1149 struct rb_calling_info *calling;
1150
1151 /* for load(true) */
1152 VALUE top_self;
1153 VALUE top_wrapper;
1154
1155 /* thread control */
1156
1157 BITFIELD(enum rb_thread_status, status, 2);
1158 /* bit flags */
1159 unsigned int has_dedicated_nt : 1;
1160 unsigned int to_kill : 1;
1161 unsigned int abort_on_exception: 1;
1162 unsigned int report_on_exception: 1;
1163 unsigned int pending_interrupt_queue_checked: 1;
1164 int8_t priority; /* -3 .. 3 (RUBY_THREAD_PRIORITY_{MIN,MAX}) */
1165 uint32_t running_time_us; /* 12500..800000 */
1166
1167 void *blocking_region_buffer;
1168
1169 VALUE thgroup;
1170 VALUE value;
1171
1172 /* temporary place of retval on OPT_CALL_THREADED_CODE */
1173#if OPT_CALL_THREADED_CODE
1174 VALUE retval;
1175#endif
1176
1177 /* async errinfo queue */
1178 VALUE pending_interrupt_queue;
1179 VALUE pending_interrupt_mask_stack;
1180
1181 /* interrupt management */
1182 rb_nativethread_lock_t interrupt_lock;
1183 struct rb_unblock_callback unblock;
1184 VALUE locking_mutex;
1185 struct rb_mutex_struct *keeping_mutexes;
1186 struct ccan_list_head interrupt_exec_tasks;
1187
1188 struct rb_waiting_list *join_list;
1189
1190 union {
1191 struct {
1192 VALUE proc;
1193 VALUE args;
1194 int kw_splat;
1195 } proc;
1196 struct {
1197 VALUE (*func)(void *);
1198 void *arg;
1199 } func;
1200 } invoke_arg;
1201
1202 enum thread_invoke_type {
1203 thread_invoke_type_none = 0,
1204 thread_invoke_type_proc,
1205 thread_invoke_type_ractor_proc,
1206 thread_invoke_type_func
1207 } invoke_type;
1208
1209 /* fiber */
1210 rb_fiber_t *root_fiber;
1211
1212 VALUE scheduler;
1213 unsigned int blocking;
1214
1215 /* misc */
1216 VALUE name;
1217 void **specific_storage;
1218
1219 struct rb_ext_config ext_config;
1220} rb_thread_t;
1221
1222static inline unsigned int
1223rb_th_serial(const rb_thread_t *th)
1224{
1225 return th ? (unsigned int)th->serial : 0;
1226}
1227
1228typedef enum {
1229 VM_DEFINECLASS_TYPE_CLASS = 0x00,
1230 VM_DEFINECLASS_TYPE_SINGLETON_CLASS = 0x01,
1231 VM_DEFINECLASS_TYPE_MODULE = 0x02,
1232 /* 0x03..0x06 is reserved */
1233 VM_DEFINECLASS_TYPE_MASK = 0x07
1234} rb_vm_defineclass_type_t;
1235
1236#define VM_DEFINECLASS_TYPE(x) ((rb_vm_defineclass_type_t)(x) & VM_DEFINECLASS_TYPE_MASK)
1237#define VM_DEFINECLASS_FLAG_SCOPED 0x08
1238#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS 0x10
1239#define VM_DEFINECLASS_SCOPED_P(x) ((x) & VM_DEFINECLASS_FLAG_SCOPED)
1240#define VM_DEFINECLASS_HAS_SUPERCLASS_P(x) \
1241 ((x) & VM_DEFINECLASS_FLAG_HAS_SUPERCLASS)
1242
1243/* iseq.c */
1244RUBY_SYMBOL_EXPORT_BEGIN
1245
1246/* node -> iseq */
1247rb_iseq_t *rb_iseq_new (const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type);
1248rb_iseq_t *rb_iseq_new_top (const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
1249rb_iseq_t *rb_iseq_new_main (const VALUE ast_value, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt);
1250rb_iseq_t *rb_iseq_new_eval (const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth);
1251rb_iseq_t *rb_iseq_new_with_opt( VALUE ast_value, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth,
1252 enum rb_iseq_type, const rb_compile_option_t*,
1253 VALUE script_lines);
1254
1255struct iseq_link_anchor;
1257 VALUE flags;
1258 VALUE reserved;
1259 void (*func)(rb_iseq_t *, struct iseq_link_anchor *, const void *);
1260 const void *data;
1261};
1262static inline struct rb_iseq_new_with_callback_callback_func *
1263rb_iseq_new_with_callback_new_callback(
1264 void (*func)(rb_iseq_t *, struct iseq_link_anchor *, const void *), const void *ptr)
1265{
1267 IMEMO_NEW(struct rb_iseq_new_with_callback_callback_func, imemo_ifunc, Qfalse);
1268 memo->func = func;
1269 memo->data = ptr;
1270
1271 return memo;
1272}
1273rb_iseq_t *rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_callback_func * ifunc,
1274 VALUE name, VALUE path, VALUE realpath, int first_lineno,
1275 const rb_iseq_t *parent, enum rb_iseq_type, const rb_compile_option_t*);
1276
1277VALUE rb_iseq_disasm(const rb_iseq_t *iseq);
1278int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child);
1279
1280VALUE rb_iseq_coverage(const rb_iseq_t *iseq);
1281
1282RUBY_EXTERN VALUE rb_cISeq;
1283RUBY_EXTERN VALUE rb_cRubyVM;
1284RUBY_EXTERN VALUE rb_mRubyVMFrozenCore;
1285RUBY_EXTERN VALUE rb_block_param_proxy;
1286RUBY_SYMBOL_EXPORT_END
1287
1288#define GetProcPtr(obj, ptr) \
1289 GetCoreDataFromValue((obj), rb_proc_t, (ptr))
1290
1291typedef struct {
1292 const struct rb_block block;
1293 unsigned int is_from_method: 1; /* bool */
1294 unsigned int is_lambda: 1; /* bool */
1295 unsigned int is_isolated: 1; /* bool */
1296} rb_proc_t;
1297
1298RUBY_SYMBOL_EXPORT_BEGIN
1299VALUE rb_proc_isolate(VALUE self);
1300VALUE rb_proc_isolate_bang(VALUE self, VALUE replace_self);
1301VALUE rb_proc_ractor_make_shareable(VALUE proc, VALUE replace_self);
1302RUBY_SYMBOL_EXPORT_END
1303
1304typedef struct {
1305 VALUE flags; /* imemo header */
1306 rb_iseq_t *iseq;
1307 const VALUE *ep;
1308 const VALUE *env;
1309 unsigned int env_size;
1310} rb_env_t;
1311
1312extern const rb_data_type_t ruby_binding_data_type;
1313
1314#define GetBindingPtr(obj, ptr) \
1315 GetCoreDataFromValue((obj), rb_binding_t, (ptr))
1316
1317typedef struct {
1318 const struct rb_block block;
1319 const VALUE pathobj;
1320 int first_lineno;
1321} rb_binding_t;
1322
1323/* used by compile time and send insn */
1324
1325enum vm_check_match_type {
1326 VM_CHECKMATCH_TYPE_WHEN = 1,
1327 VM_CHECKMATCH_TYPE_CASE = 2,
1328 VM_CHECKMATCH_TYPE_RESCUE = 3
1329};
1330
1331#define VM_CHECKMATCH_TYPE_MASK 0x03
1332#define VM_CHECKMATCH_ARRAY 0x04
1333
1334enum vm_opt_newarray_send_type {
1335 VM_OPT_NEWARRAY_SEND_MAX = 1,
1336 VM_OPT_NEWARRAY_SEND_MIN = 2,
1337 VM_OPT_NEWARRAY_SEND_HASH = 3,
1338 VM_OPT_NEWARRAY_SEND_PACK = 4,
1339 VM_OPT_NEWARRAY_SEND_PACK_BUFFER = 5,
1340 VM_OPT_NEWARRAY_SEND_INCLUDE_P = 6,
1341};
1342
1343enum vm_special_object_type {
1344 VM_SPECIAL_OBJECT_VMCORE = 1,
1345 VM_SPECIAL_OBJECT_CBASE,
1346 VM_SPECIAL_OBJECT_CONST_BASE
1347};
1348
1349enum vm_svar_index {
1350 VM_SVAR_LASTLINE = 0, /* $_ */
1351 VM_SVAR_BACKREF = 1, /* $~ */
1352
1353 VM_SVAR_EXTRA_START = 2,
1354 VM_SVAR_FLIPFLOP_START = 2 /* flipflop */
1355};
1356
1357/* inline cache */
1358typedef struct iseq_inline_constant_cache *IC;
1359typedef struct iseq_inline_iv_cache_entry *IVC;
1360typedef struct iseq_inline_cvar_cache_entry *ICVARC;
1361typedef union iseq_inline_storage_entry *ISE;
1362typedef const struct rb_callinfo *CALL_INFO;
1363typedef const struct rb_callcache *CALL_CACHE;
1364typedef struct rb_call_data *CALL_DATA;
1365
1366typedef VALUE CDHASH;
1367
1368#ifndef FUNC_FASTCALL
1369#define FUNC_FASTCALL(x) x
1370#endif
1371
1372typedef rb_control_frame_t *
1373 (FUNC_FASTCALL(*rb_insn_func_t))(rb_execution_context_t *, rb_control_frame_t *);
1374
1375#define VM_TAGGED_PTR_SET(p, tag) ((VALUE)(p) | (tag))
1376#define VM_TAGGED_PTR_REF(v, mask) ((void *)((v) & ~mask))
1377
1378#define GC_GUARDED_PTR(p) VM_TAGGED_PTR_SET((p), 0x01)
1379#define GC_GUARDED_PTR_REF(p) VM_TAGGED_PTR_REF((p), 0x03)
1380#define GC_GUARDED_PTR_P(p) (((VALUE)(p)) & 0x01)
1381
1382enum vm_frame_env_flags {
1383 /* Frame/Environment flag bits:
1384 * MMMM MMMM MMMM MMMM ___F FFFF FFFE EEEX (LSB)
1385 *
1386 * X : tag for GC marking (It seems as Fixnum)
1387 * EEE : 4 bits Env flags
1388 * FF..: 8 bits Frame flags
1389 * MM..: 15 bits frame magic (to check frame corruption)
1390 */
1391
1392 /* frame types */
1393 VM_FRAME_MAGIC_METHOD = 0x11110001,
1394 VM_FRAME_MAGIC_BLOCK = 0x22220001,
1395 VM_FRAME_MAGIC_CLASS = 0x33330001,
1396 VM_FRAME_MAGIC_TOP = 0x44440001,
1397 VM_FRAME_MAGIC_CFUNC = 0x55550001,
1398 VM_FRAME_MAGIC_IFUNC = 0x66660001,
1399 VM_FRAME_MAGIC_EVAL = 0x77770001,
1400 VM_FRAME_MAGIC_RESCUE = 0x78880001,
1401 VM_FRAME_MAGIC_DUMMY = 0x79990001,
1402
1403 VM_FRAME_MAGIC_MASK = 0x7fff0001,
1404
1405 /* frame flag */
1406 VM_FRAME_FLAG_FINISH = 0x0020,
1407 VM_FRAME_FLAG_BMETHOD = 0x0040,
1408 VM_FRAME_FLAG_CFRAME = 0x0080,
1409 VM_FRAME_FLAG_LAMBDA = 0x0100,
1410 VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200,
1411 VM_FRAME_FLAG_CFRAME_KW = 0x0400,
1412 VM_FRAME_FLAG_PASSED = 0x0800,
1413 VM_FRAME_FLAG_BOX_REQUIRE = 0x1000,
1414
1415 /* env flag */
1416 VM_ENV_FLAG_LOCAL = 0x0002,
1417 VM_ENV_FLAG_ESCAPED = 0x0004,
1418 VM_ENV_FLAG_WB_REQUIRED = 0x0008,
1419 VM_ENV_FLAG_ISOLATED = 0x0010,
1420};
1421
1422#define VM_ENV_DATA_SIZE ( 3)
1423
1424#define VM_ENV_DATA_INDEX_ME_CREF (-2) /* ep[-2] */
1425#define VM_ENV_DATA_INDEX_SPECVAL (-1) /* ep[-1] */
1426#define VM_ENV_DATA_INDEX_FLAGS ( 0) /* ep[ 0] */
1427#define VM_ENV_DATA_INDEX_ENV ( 1) /* ep[ 1] */
1428
1429#define VM_ENV_INDEX_LAST_LVAR (-VM_ENV_DATA_SIZE)
1430
1431static inline void VM_FORCE_WRITE_SPECIAL_CONST(const VALUE *ptr, VALUE special_const_value);
1432
1433static inline void
1434VM_ENV_FLAGS_SET(const VALUE *ep, VALUE flag)
1435{
1436 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1437 VM_ASSERT(FIXNUM_P(flags));
1438 VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags | flag);
1439}
1440
1441static inline void
1442VM_ENV_FLAGS_UNSET(const VALUE *ep, VALUE flag)
1443{
1444 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1445 VM_ASSERT(FIXNUM_P(flags));
1446 VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags & ~flag);
1447}
1448
1449static inline unsigned long
1450VM_ENV_FLAGS(const VALUE *ep, long flag)
1451{
1452 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1453 VM_ASSERT(FIXNUM_P(flags));
1454 return flags & flag;
1455}
1456
1457static inline unsigned long
1458VM_ENV_FLAGS_UNCHECKED(const VALUE *ep, long flag)
1459{
1460 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1461 return flags & flag;
1462}
1463
1464static inline unsigned long
1465VM_ENV_FRAME_TYPE_P(const VALUE *ep, unsigned long frame_type)
1466{
1467 return VM_ENV_FLAGS(ep, VM_FRAME_MAGIC_MASK) == frame_type;
1468}
1469
1470static inline unsigned long
1471VM_FRAME_TYPE(const rb_control_frame_t *cfp)
1472{
1473 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_MAGIC_MASK);
1474}
1475
1476static inline unsigned long
1477VM_FRAME_TYPE_UNCHECKED(const rb_control_frame_t *cfp)
1478{
1479 return VM_ENV_FLAGS_UNCHECKED(cfp->ep, VM_FRAME_MAGIC_MASK);
1480}
1481
1482static inline int
1483VM_FRAME_LAMBDA_P(const rb_control_frame_t *cfp)
1484{
1485 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_LAMBDA) != 0;
1486}
1487
1488static inline int
1489VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp)
1490{
1491 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0;
1492}
1493
1494static inline int
1495VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp)
1496{
1497 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_FINISH) != 0;
1498}
1499
1500static inline int
1501VM_FRAME_FINISHED_P_UNCHECKED(const rb_control_frame_t *cfp)
1502{
1503 return VM_ENV_FLAGS_UNCHECKED(cfp->ep, VM_FRAME_FLAG_FINISH) != 0;
1504}
1505
1506static inline int
1507VM_FRAME_BMETHOD_P(const rb_control_frame_t *cfp)
1508{
1509 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_BMETHOD) != 0;
1510}
1511
1512static inline int
1513rb_obj_is_iseq(VALUE iseq)
1514{
1515 return imemo_type_p(iseq, imemo_iseq);
1516}
1517
1518#if VM_CHECK_MODE > 0
1519#define RUBY_VM_NORMAL_ISEQ_P(iseq) rb_obj_is_iseq((VALUE)iseq)
1520#endif
1521
1522static inline int
1523VM_FRAME_CFRAME_P(const rb_control_frame_t *cfp)
1524{
1525 int cframe_p = VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME) != 0;
1526 VM_ASSERT(RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) != cframe_p ||
1527 (VM_FRAME_TYPE(cfp) & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY);
1528 return cframe_p;
1529}
1530
1531static inline int
1532VM_FRAME_CFRAME_P_UNCHECKED(const rb_control_frame_t *cfp)
1533{
1534 return VM_ENV_FLAGS_UNCHECKED(cfp->ep, VM_FRAME_FLAG_CFRAME) != 0;
1535}
1536
1537static inline int
1538VM_FRAME_RUBYFRAME_P(const rb_control_frame_t *cfp)
1539{
1540 return !VM_FRAME_CFRAME_P(cfp);
1541}
1542
1543static inline int
1544VM_FRAME_RUBYFRAME_P_UNCHECKED(const rb_control_frame_t *cfp)
1545{
1546 return !VM_FRAME_CFRAME_P_UNCHECKED(cfp);
1547}
1548
1549static inline int
1550VM_FRAME_NS_REQUIRE_P(const rb_control_frame_t *cfp)
1551{
1552 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_BOX_REQUIRE) != 0;
1553}
1554
1555#define RUBYVM_CFUNC_FRAME_P(cfp) \
1556 (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
1557
1558#define VM_GUARDED_PREV_EP(ep) GC_GUARDED_PTR(ep)
1559#define VM_BLOCK_HANDLER_NONE 0
1560
1561static inline int
1562VM_ENV_LOCAL_P(const VALUE *ep)
1563{
1564 return VM_ENV_FLAGS(ep, VM_ENV_FLAG_LOCAL) ? 1 : 0;
1565}
1566
1567static inline int
1568VM_ENV_LOCAL_P_UNCHECKED(const VALUE *ep)
1569{
1570 return VM_ENV_FLAGS_UNCHECKED(ep, VM_ENV_FLAG_LOCAL) ? 1 : 0;
1571}
1572
1573static inline const VALUE *
1574VM_ENV_PREV_EP_UNCHECKED(const VALUE *ep)
1575{
1576 return GC_GUARDED_PTR_REF(ep[VM_ENV_DATA_INDEX_SPECVAL]);
1577}
1578
1579static inline const VALUE *
1580VM_ENV_PREV_EP(const VALUE *ep)
1581{
1582 VM_ASSERT(VM_ENV_LOCAL_P(ep) == 0);
1583 return VM_ENV_PREV_EP_UNCHECKED(ep);
1584}
1585
1586static inline bool
1587VM_ENV_BOXED_P(const VALUE *ep)
1588{
1589 return VM_ENV_FRAME_TYPE_P(ep, VM_FRAME_MAGIC_CLASS) || VM_ENV_FRAME_TYPE_P(ep, VM_FRAME_MAGIC_TOP);
1590}
1591
1592static inline VALUE
1593VM_ENV_BLOCK_HANDLER(const VALUE *ep)
1594{
1595 if (VM_ENV_BOXED_P(ep)) {
1596 VM_ASSERT(VM_ENV_LOCAL_P(ep));
1597 return VM_BLOCK_HANDLER_NONE;
1598 }
1599
1600 VM_ASSERT(VM_ENV_LOCAL_P(ep));
1601 return ep[VM_ENV_DATA_INDEX_SPECVAL];
1602}
1603
1604static inline const rb_box_t *
1605VM_ENV_BOX(const VALUE *ep)
1606{
1607 VM_ASSERT(VM_ENV_BOXED_P(ep));
1608 VM_ASSERT(VM_ENV_LOCAL_P(ep));
1609 return (const rb_box_t *)GC_GUARDED_PTR_REF(ep[VM_ENV_DATA_INDEX_SPECVAL]);
1610}
1611
1612static inline const rb_box_t *
1613VM_ENV_BOX_UNCHECKED(const VALUE *ep)
1614{
1615 return (const rb_box_t *)GC_GUARDED_PTR_REF(ep[VM_ENV_DATA_INDEX_SPECVAL]);
1616}
1617
1618#if VM_CHECK_MODE > 0
1619int rb_vm_ep_in_heap_p(const VALUE *ep);
1620#endif
1621
1622static inline int
1623VM_ENV_ESCAPED_P(const VALUE *ep)
1624{
1625 VM_ASSERT(rb_vm_ep_in_heap_p(ep) == !!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED));
1626 return VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) ? 1 : 0;
1627}
1628
1630static inline VALUE
1631VM_ENV_ENVVAL(const VALUE *ep)
1632{
1633 VALUE envval = ep[VM_ENV_DATA_INDEX_ENV];
1634 VM_ASSERT(VM_ENV_ESCAPED_P(ep));
1635 VM_ASSERT(envval == Qundef || imemo_type_p(envval, imemo_env));
1636 return envval;
1637}
1638
1640static inline const rb_env_t *
1641VM_ENV_ENVVAL_PTR(const VALUE *ep)
1642{
1643 return (const rb_env_t *)VM_ENV_ENVVAL(ep);
1644}
1645
1646static inline const rb_env_t *
1647vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq)
1648{
1649 rb_env_t *env = IMEMO_NEW(rb_env_t, imemo_env, (VALUE)iseq);
1650 env->ep = env_ep;
1651 env->env = env_body;
1652 env->env_size = env_size;
1653 env_ep[VM_ENV_DATA_INDEX_ENV] = (VALUE)env;
1654 return env;
1655}
1656
1657static inline void
1658VM_FORCE_WRITE(const VALUE *ptr, VALUE v)
1659{
1660 *((VALUE *)ptr) = v;
1661}
1662
1663static inline void
1664VM_FORCE_WRITE_SPECIAL_CONST(const VALUE *ptr, VALUE special_const_value)
1665{
1666 VM_ASSERT(RB_SPECIAL_CONST_P(special_const_value));
1667 VM_FORCE_WRITE(ptr, special_const_value);
1668}
1669
1670static inline void
1671VM_STACK_ENV_WRITE(const VALUE *ep, int index, VALUE v)
1672{
1673 VM_ASSERT(VM_ENV_FLAGS(ep, VM_ENV_FLAG_WB_REQUIRED) == 0);
1674 VM_FORCE_WRITE(&ep[index], v);
1675}
1676
1677const VALUE *rb_vm_ep_local_ep(const VALUE *ep);
1678const VALUE *rb_vm_proc_local_ep(VALUE proc);
1679void rb_vm_block_ep_update(VALUE obj, const struct rb_block *dst, const VALUE *ep);
1680void rb_vm_block_copy(VALUE obj, const struct rb_block *dst, const struct rb_block *src);
1681
1682VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp);
1683
1684#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ((cfp)+1)
1685#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) ((cfp)-1)
1686
1687#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \
1688 ((void *)(ecfp) > (void *)(cfp))
1689
1690static inline const rb_control_frame_t *
1691RUBY_VM_END_CONTROL_FRAME(const rb_execution_context_t *ec)
1692{
1693 return (rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size);
1694}
1695
1696static inline int
1697RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
1698{
1699 return !RUBY_VM_VALID_CONTROL_FRAME_P(cfp, RUBY_VM_END_CONTROL_FRAME(ec));
1700}
1701
1702static inline int
1703VM_BH_ISEQ_BLOCK_P(VALUE block_handler)
1704{
1705 if ((block_handler & 0x03) == 0x01) {
1706#if VM_CHECK_MODE > 0
1707 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1708 VM_ASSERT(imemo_type_p(captured->code.val, imemo_iseq));
1709#endif
1710 return 1;
1711 }
1712 else {
1713 return 0;
1714 }
1715}
1716
1717static inline VALUE
1718VM_BH_FROM_ISEQ_BLOCK(const struct rb_captured_block *captured)
1719{
1720 VALUE block_handler = VM_TAGGED_PTR_SET(captured, 0x01);
1721 VM_ASSERT(VM_BH_ISEQ_BLOCK_P(block_handler));
1722 return block_handler;
1723}
1724
1725static inline const struct rb_captured_block *
1726VM_BH_TO_ISEQ_BLOCK(VALUE block_handler)
1727{
1728 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1729 VM_ASSERT(VM_BH_ISEQ_BLOCK_P(block_handler));
1730 return captured;
1731}
1732
1733static inline int
1734VM_BH_IFUNC_P(VALUE block_handler)
1735{
1736 if ((block_handler & 0x03) == 0x03) {
1737#if VM_CHECK_MODE > 0
1738 struct rb_captured_block *captured = (void *)(block_handler & ~0x03);
1739 VM_ASSERT(imemo_type_p(captured->code.val, imemo_ifunc));
1740#endif
1741 return 1;
1742 }
1743 else {
1744 return 0;
1745 }
1746}
1747
1748static inline VALUE
1749VM_BH_FROM_IFUNC_BLOCK(const struct rb_captured_block *captured)
1750{
1751 VALUE block_handler = VM_TAGGED_PTR_SET(captured, 0x03);
1752 VM_ASSERT(VM_BH_IFUNC_P(block_handler));
1753 return block_handler;
1754}
1755
1756static inline const struct rb_captured_block *
1757VM_BH_TO_IFUNC_BLOCK(VALUE block_handler)
1758{
1759 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1760 VM_ASSERT(VM_BH_IFUNC_P(block_handler));
1761 return captured;
1762}
1763
1764static inline const struct rb_captured_block *
1765VM_BH_TO_CAPT_BLOCK(VALUE block_handler)
1766{
1767 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1768 VM_ASSERT(VM_BH_IFUNC_P(block_handler) || VM_BH_ISEQ_BLOCK_P(block_handler));
1769 return captured;
1770}
1771
1772static inline enum rb_block_handler_type
1773vm_block_handler_type(VALUE block_handler)
1774{
1775 if (VM_BH_ISEQ_BLOCK_P(block_handler)) {
1776 return block_handler_type_iseq;
1777 }
1778 else if (VM_BH_IFUNC_P(block_handler)) {
1779 return block_handler_type_ifunc;
1780 }
1781 else if (SYMBOL_P(block_handler)) {
1782 return block_handler_type_symbol;
1783 }
1784 else {
1785 VM_ASSERT(rb_obj_is_proc(block_handler));
1786 return block_handler_type_proc;
1787 }
1788}
1789
1790static inline void
1791vm_block_handler_verify(MAYBE_UNUSED(VALUE block_handler))
1792{
1793 VM_ASSERT(block_handler == VM_BLOCK_HANDLER_NONE ||
1794 (vm_block_handler_type(block_handler), 1));
1795}
1796
1797static inline enum rb_block_type
1798vm_block_type(const struct rb_block *block)
1799{
1800#if VM_CHECK_MODE > 0
1801 switch (block->type) {
1802 case block_type_iseq:
1803 VM_ASSERT(imemo_type_p(block->as.captured.code.val, imemo_iseq));
1804 break;
1805 case block_type_ifunc:
1806 VM_ASSERT(imemo_type_p(block->as.captured.code.val, imemo_ifunc));
1807 break;
1808 case block_type_symbol:
1809 VM_ASSERT(SYMBOL_P(block->as.symbol));
1810 break;
1811 case block_type_proc:
1812 VM_ASSERT(rb_obj_is_proc(block->as.proc));
1813 break;
1814 }
1815#endif
1816 return block->type;
1817}
1818
1819static inline void
1820vm_block_type_set(const struct rb_block *block, enum rb_block_type type)
1821{
1822 struct rb_block *mb = (struct rb_block *)block;
1823 mb->type = type;
1824}
1825
1826static inline const struct rb_block *
1827vm_proc_block(VALUE procval)
1828{
1829 VM_ASSERT(rb_obj_is_proc(procval));
1830 return &((rb_proc_t *)RTYPEDDATA_DATA(procval))->block;
1831}
1832
1833static inline const rb_iseq_t *vm_block_iseq(const struct rb_block *block);
1834static inline const VALUE *vm_block_ep(const struct rb_block *block);
1835
1836static inline const rb_iseq_t *
1837vm_proc_iseq(VALUE procval)
1838{
1839 return vm_block_iseq(vm_proc_block(procval));
1840}
1841
1842static inline const VALUE *
1843vm_proc_ep(VALUE procval)
1844{
1845 return vm_block_ep(vm_proc_block(procval));
1846}
1847
1848static inline const rb_iseq_t *
1849vm_block_iseq(const struct rb_block *block)
1850{
1851 switch (vm_block_type(block)) {
1852 case block_type_iseq: return rb_iseq_check(block->as.captured.code.iseq);
1853 case block_type_proc: return vm_proc_iseq(block->as.proc);
1854 case block_type_ifunc:
1855 case block_type_symbol: return NULL;
1856 }
1857 VM_UNREACHABLE(vm_block_iseq);
1858 return NULL;
1859}
1860
1861static inline const VALUE *
1862vm_block_ep(const struct rb_block *block)
1863{
1864 switch (vm_block_type(block)) {
1865 case block_type_iseq:
1866 case block_type_ifunc: return block->as.captured.ep;
1867 case block_type_proc: return vm_proc_ep(block->as.proc);
1868 case block_type_symbol: return NULL;
1869 }
1870 VM_UNREACHABLE(vm_block_ep);
1871 return NULL;
1872}
1873
1874static inline VALUE
1875vm_block_self(const struct rb_block *block)
1876{
1877 switch (vm_block_type(block)) {
1878 case block_type_iseq:
1879 case block_type_ifunc:
1880 return block->as.captured.self;
1881 case block_type_proc:
1882 return vm_block_self(vm_proc_block(block->as.proc));
1883 case block_type_symbol:
1884 return Qundef;
1885 }
1886 VM_UNREACHABLE(vm_block_self);
1887 return Qundef;
1888}
1889
1890static inline VALUE
1891VM_BH_TO_SYMBOL(VALUE block_handler)
1892{
1893 VM_ASSERT(SYMBOL_P(block_handler));
1894 return block_handler;
1895}
1896
1897static inline VALUE
1898VM_BH_FROM_SYMBOL(VALUE symbol)
1899{
1900 VM_ASSERT(SYMBOL_P(symbol));
1901 return symbol;
1902}
1903
1904static inline VALUE
1905VM_BH_TO_PROC(VALUE block_handler)
1906{
1907 VM_ASSERT(rb_obj_is_proc(block_handler));
1908 return block_handler;
1909}
1910
1911static inline VALUE
1912VM_BH_FROM_PROC(VALUE procval)
1913{
1914 VM_ASSERT(rb_obj_is_proc(procval));
1915 return procval;
1916}
1917
1918/* VM related object allocate functions */
1919VALUE rb_thread_alloc(VALUE klass);
1920VALUE rb_binding_alloc(VALUE klass);
1921VALUE rb_proc_alloc(VALUE klass);
1922VALUE rb_proc_dup(VALUE self);
1923
1924/* for debug */
1925extern bool rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
1926extern bool rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *);
1927extern bool rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
1928
1929#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr)
1930#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr)
1931bool rb_vm_bugreport(const void *, FILE *);
1932typedef void (*ruby_sighandler_t)(int);
1933RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
1934NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));
1935
1936/* functions about thread/vm execution */
1937RUBY_SYMBOL_EXPORT_BEGIN
1938VALUE rb_iseq_eval(const rb_iseq_t *iseq, const rb_box_t *box);
1939VALUE rb_iseq_eval_main(const rb_iseq_t *iseq);
1940VALUE rb_iseq_path(const rb_iseq_t *iseq);
1941VALUE rb_iseq_realpath(const rb_iseq_t *iseq);
1942RUBY_SYMBOL_EXPORT_END
1943
1944VALUE rb_iseq_pathobj_new(VALUE path, VALUE realpath);
1945void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath);
1946
1947int rb_ec_frame_method_id_and_class(const rb_execution_context_t *ec, ID *idp, ID *called_idp, VALUE *klassp);
1948void rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause);
1949
1950VALUE rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
1951
1952VALUE rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda);
1953static inline VALUE
1954rb_vm_make_proc(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass)
1955{
1956 return rb_vm_make_proc_lambda(ec, captured, klass, 0);
1957}
1958
1959static inline VALUE
1960rb_vm_make_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass)
1961{
1962 return rb_vm_make_proc_lambda(ec, captured, klass, 1);
1963}
1964
1965VALUE rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp);
1966VALUE rb_vm_env_local_variables(const rb_env_t *env);
1967VALUE rb_vm_env_numbered_parameters(const rb_env_t *env);
1968const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env);
1969const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars);
1970void rb_vm_inc_const_missing_count(void);
1971VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc,
1972 const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat);
1973void rb_vm_pop_frame_no_int(rb_execution_context_t *ec);
1974void rb_vm_pop_frame(rb_execution_context_t *ec);
1975
1976void rb_thread_start_timer_thread(void);
1977void rb_thread_stop_timer_thread(void);
1978void rb_thread_reset_timer_thread(void);
1979void rb_thread_wakeup_timer_thread(int);
1980
1981static inline void
1982rb_vm_living_threads_init(rb_vm_t *vm)
1983{
1984 ccan_list_head_init(&vm->workqueue);
1985 ccan_list_head_init(&vm->ractor.set);
1986#ifdef RUBY_THREAD_PTHREAD_H
1987 ccan_list_head_init(&vm->ractor.sched.zombie_threads);
1988#endif
1989}
1990
1991typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
1992rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1993rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1994VALUE *rb_vm_svar_lep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1995int rb_vm_get_sourceline(const rb_control_frame_t *);
1996void rb_vm_stack_to_heap(rb_execution_context_t *ec);
1997void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame);
1998void rb_thread_malloc_stack_set(rb_thread_t *th, void *stack);
1999rb_thread_t * ruby_thread_from_native(void);
2000int ruby_thread_set_native(rb_thread_t *th);
2001int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp);
2002void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp);
2003void rb_vm_env_write(const VALUE *ep, int index, VALUE v);
2004VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler);
2005
2006void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE exception_class, VALUE mesg);
2007
2008#define rb_vm_register_special_exception(sp, e, m) \
2009 rb_vm_register_special_exception_str(sp, e, rb_usascii_str_new_static((m), (long)rb_strlen_lit(m)))
2010
2011void rb_gc_mark_machine_context(const rb_execution_context_t *ec);
2012
2013rb_cref_t *rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass);
2014
2015const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
2016const rb_callable_method_entry_t *rb_vm_frame_method_entry_unchecked(const rb_control_frame_t *cfp);
2017
2018#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
2019
2020#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) do { \
2021 STATIC_ASSERT(sizeof_sp, sizeof(*(sp)) == sizeof(VALUE)); \
2022 STATIC_ASSERT(sizeof_cfp, sizeof(*(cfp)) == sizeof(rb_control_frame_t)); \
2023 const struct rb_control_frame_struct *bound = (void *)&(sp)[(margin)]; \
2024 if (UNLIKELY((cfp) <= &bound[1])) { \
2025 vm_stackoverflow(); \
2026 } \
2027} while (0)
2028
2029#define CHECK_VM_STACK_OVERFLOW(cfp, margin) \
2030 CHECK_VM_STACK_OVERFLOW0((cfp), (cfp)->sp, (margin))
2031
2032VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr);
2033
2034rb_execution_context_t *rb_vm_main_ractor_ec(rb_vm_t *vm); // ractor.c
2035
2036/* for thread */
2037
2038#if RUBY_VM_THREAD_MODEL == 2
2039
2040RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; // ractor.c
2041RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr;
2042RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags;
2043RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags; // only ever added to
2044RUBY_EXTERN unsigned int ruby_vm_iseq_events_enabled;
2045RUBY_EXTERN unsigned int ruby_vm_c_events_enabled;
2046
2047#define GET_VM() rb_current_vm()
2048#define GET_RACTOR() rb_current_ractor()
2049#define GET_THREAD() rb_current_thread()
2050#define GET_EC() rb_current_execution_context(true)
2051
2052static inline rb_serial_t
2053rb_ec_serial(struct rb_execution_context_struct *ec)
2054{
2055 VM_ASSERT(ec->serial >= 1);
2056 return ec->serial;
2057}
2058
2059static inline rb_thread_t *
2060rb_ec_thread_ptr(const rb_execution_context_t *ec)
2061{
2062 return ec->thread_ptr;
2063}
2064
2065static inline rb_ractor_t *
2066rb_ec_ractor_ptr(const rb_execution_context_t *ec)
2067{
2068 const rb_thread_t *th = rb_ec_thread_ptr(ec);
2069 if (th) {
2070 VM_ASSERT(th->ractor != NULL);
2071 return th->ractor;
2072 }
2073 else {
2074 return NULL;
2075 }
2076}
2077
2078static inline rb_serial_t
2079rb_ec_ractor_id(const rb_execution_context_t *ec)
2080{
2081 rb_serial_t ractor_id = ec->ractor_id;
2082 RUBY_ASSERT(ractor_id);
2083 return ractor_id;
2084}
2085
2086static inline rb_vm_t *
2087rb_ec_vm_ptr(const rb_execution_context_t *ec)
2088{
2089 const rb_thread_t *th = rb_ec_thread_ptr(ec);
2090 if (th) {
2091 return th->vm;
2092 }
2093 else {
2094 return NULL;
2095 }
2096}
2097
2098NOINLINE(struct rb_execution_context_struct *rb_current_ec_noinline(void));
2099
2100static inline rb_execution_context_t *
2101rb_current_execution_context(bool expect_ec)
2102{
2103#ifdef RB_THREAD_LOCAL_SPECIFIER
2104 #ifdef RB_THREAD_CURRENT_EC_NOINLINE
2105 rb_execution_context_t * volatile ec = rb_current_ec();
2106 #else
2107 rb_execution_context_t * volatile ec = ruby_current_ec;
2108 #endif
2109
2110 /* On the shared objects, `__tls_get_addr()` is used to access the TLS
2111 * and the address of the `ruby_current_ec` can be stored on a function
2112 * frame. However, this address can be mis-used after native thread
2113 * migration of a coroutine.
2114 * 1) Get `ptr = &ruby_current_ec` on NT1 and store it on the frame.
2115 * 2) Context switch and resume it on the NT2.
2116 * 3) `ptr` is used on NT2 but it accesses the TLS of NT1.
2117 * This assertion checks such misusage.
2118 *
2119 * To avoid accidents, `GET_EC()` should be called once on the frame.
2120 * Note that inlining can produce the problem.
2121 */
2122 VM_ASSERT(ec == rb_current_ec_noinline());
2123#else
2124 rb_execution_context_t * volatile ec = native_tls_get(ruby_current_ec_key);
2125#endif
2126 VM_ASSERT(!expect_ec || ec != NULL);
2127 return ec;
2128}
2129
2130static inline rb_thread_t *
2131rb_current_thread(void)
2132{
2133 const rb_execution_context_t *ec = GET_EC();
2134 return rb_ec_thread_ptr(ec);
2135}
2136
2137static inline rb_ractor_t *
2138rb_current_ractor_raw(bool expect)
2139{
2140 if (ruby_single_main_ractor) {
2141 return ruby_single_main_ractor;
2142 }
2143 else {
2144 const rb_execution_context_t *ec = rb_current_execution_context(expect);
2145 return (expect || ec) ? rb_ec_ractor_ptr(ec) : NULL;
2146 }
2147}
2148
2149static inline rb_ractor_t *
2150rb_current_ractor(void)
2151{
2152 return rb_current_ractor_raw(true);
2153}
2154
2155static inline rb_vm_t *
2156rb_current_vm(void)
2157{
2158#if 0 // TODO: reconsider the assertions
2159 VM_ASSERT(ruby_current_vm_ptr == NULL ||
2160 ruby_current_execution_context_ptr == NULL ||
2161 rb_ec_thread_ptr(GET_EC()) == NULL ||
2162 rb_ec_thread_ptr(GET_EC())->status == THREAD_KILLED ||
2163 rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr);
2164#endif
2165
2166 return ruby_current_vm_ptr;
2167}
2168
2169void rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec,
2170 unsigned int recorded_lock_rec,
2171 unsigned int current_lock_rec);
2172
2173/* This technically is a data race, as it's checked without the lock, however we
2174 * check against a value only our own thread will write. */
2175NO_SANITIZE("thread", static inline bool
2176vm_locked_by_ractor_p(rb_vm_t *vm, rb_ractor_t *cr))
2177{
2178 VM_ASSERT(cr == GET_RACTOR());
2179 return vm->ractor.sync.lock_owner == cr;
2180}
2181
2182static inline unsigned int
2183rb_ec_vm_lock_rec(const rb_execution_context_t *ec)
2184{
2185 rb_vm_t *vm = rb_ec_vm_ptr(ec);
2186
2187 if (!vm_locked_by_ractor_p(vm, rb_ec_ractor_ptr(ec))) {
2188 return 0;
2189 }
2190 else {
2191 return vm->ractor.sync.lock_rec;
2192 }
2193}
2194
2195#else
2196#error "unsupported thread model"
2197#endif
2198
2199enum {
2200 TIMER_INTERRUPT_MASK = 0x01,
2201 PENDING_INTERRUPT_MASK = 0x02,
2202 POSTPONED_JOB_INTERRUPT_MASK = 0x04,
2203 TRAP_INTERRUPT_MASK = 0x08,
2204 TERMINATE_INTERRUPT_MASK = 0x10,
2205 VM_BARRIER_INTERRUPT_MASK = 0x20,
2206};
2207
2208#define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK)
2209#define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK)
2210#define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK)
2211#define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK)
2212#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK)
2213#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK)
2214
2215static inline bool
2216RUBY_VM_INTERRUPTED(rb_execution_context_t *ec)
2217{
2218 return (ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec->interrupt_mask) & (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK));
2219}
2220
2221static inline bool
2222RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec)
2223{
2224#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
2225 uint32_t current_clock = rb_ec_vm_ptr(ec)->clock;
2226
2227 if (current_clock != ec->checked_clock) {
2228 ec->checked_clock = current_clock;
2229 RUBY_VM_SET_TIMER_INTERRUPT(ec);
2230 }
2231#endif
2232 return ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec)->interrupt_mask;
2233}
2234
2235VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
2236int rb_signal_buff_size(void);
2237int rb_signal_exec(rb_thread_t *th, int sig);
2238void rb_threadptr_check_signal(rb_thread_t *mth);
2239void rb_threadptr_signal_raise(rb_thread_t *th, int sig);
2240void rb_threadptr_interrupt_raise(rb_thread_t *th);
2241void rb_threadptr_signal_exit(rb_thread_t *th);
2242int rb_threadptr_execute_interrupts(rb_thread_t *, int);
2243void rb_threadptr_interrupt(rb_thread_t *th);
2244void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th);
2245void rb_threadptr_pending_interrupt_clear(rb_thread_t *th);
2246void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v);
2247VALUE rb_ec_get_errinfo(const rb_execution_context_t *ec);
2248void rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo);
2249void rb_execution_context_update(rb_execution_context_t *ec);
2250void rb_execution_context_mark(const rb_execution_context_t *ec);
2251void rb_fiber_close(rb_fiber_t *fib);
2252void Init_native_thread(rb_thread_t *th);
2253int rb_vm_check_ints_blocking(rb_execution_context_t *ec);
2254
2255// vm_sync.h
2256void rb_vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond);
2257void rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec);
2258
2259#define RUBY_VM_CHECK_INTS(ec) rb_vm_check_ints(ec)
2260static inline void
2261rb_vm_check_ints(rb_execution_context_t *ec)
2262{
2263#ifdef RUBY_ASSERT_CRITICAL_SECTION
2264 VM_ASSERT(ruby_assert_critical_section_entered == 0);
2265#endif
2266
2267 VM_ASSERT(ec == rb_current_ec_noinline());
2268
2269 if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {
2270 rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);
2271 }
2272}
2273
2274/* tracer */
2275
2277 rb_event_flag_t event;
2278 rb_execution_context_t *ec;
2279 const rb_control_frame_t *cfp;
2280 VALUE self;
2281 ID id;
2282 ID called_id;
2283 VALUE klass;
2284 VALUE data;
2285
2286 int klass_solved;
2287
2288 /* calc from cfp */
2289 int lineno;
2290 VALUE path;
2291};
2292
2293void rb_hook_list_mark(rb_hook_list_t *hooks);
2294void rb_hook_list_mark_and_move(rb_hook_list_t *hooks);
2295void rb_hook_list_free(rb_hook_list_t *hooks);
2296void rb_hook_list_connect_local_tracepoint(rb_hook_list_t *list, VALUE tpval, unsigned int target_line);
2297bool rb_hook_list_remove_local_tracepoint(rb_hook_list_t *list, VALUE tpval);
2298unsigned int rb_hook_list_count(rb_hook_list_t *list);
2299
2300void rb_exec_event_hooks(struct rb_trace_arg_struct *trace_arg, rb_hook_list_t *hooks, int pop_p);
2301
2302#define EXEC_EVENT_HOOK_ORIG(ec_, hooks_, flag_, self_, id_, called_id_, klass_, data_, pop_p_) do { \
2303 const rb_event_flag_t flag_arg_ = (flag_); \
2304 rb_hook_list_t *hooks_arg_ = (hooks_); \
2305 if (UNLIKELY((hooks_arg_)->events & (flag_arg_))) { \
2306 /* defer evaluating the other arguments */ \
2307 rb_exec_event_hook_orig(ec_, hooks_arg_, flag_arg_, self_, id_, called_id_, klass_, data_, pop_p_); \
2308 } \
2309} while (0)
2310
2311static inline void
2312rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_event_flag_t flag,
2313 VALUE self, ID id, ID called_id, VALUE klass, VALUE data, int pop_p)
2314{
2315 struct rb_trace_arg_struct trace_arg;
2316
2317 VM_ASSERT((hooks->events & flag) != 0);
2318
2319 trace_arg.event = flag;
2320 trace_arg.ec = ec;
2321 trace_arg.cfp = ec->cfp;
2322 trace_arg.self = self;
2323 trace_arg.id = id;
2324 trace_arg.called_id = called_id;
2325 trace_arg.klass = klass;
2326 trace_arg.data = data;
2327 trace_arg.path = Qundef;
2328 trace_arg.klass_solved = 0;
2329
2330 rb_exec_event_hooks(&trace_arg, hooks, pop_p);
2331}
2332
2334 VALUE self;
2335 uint32_t id;
2336 rb_hook_list_t hooks;
2337 st_table *targeted_hooks; // also called "local hooks". {ISEQ => hook_list, def => hook_list...}
2338 unsigned int targeted_hooks_cnt; // ex: tp.enabled(target: method(:puts))
2339};
2340
2341static inline rb_hook_list_t *
2342rb_ec_ractor_hooks(const rb_execution_context_t *ec)
2343{
2344 struct rb_ractor_pub *cr_pub = (struct rb_ractor_pub *)rb_ec_ractor_ptr(ec);
2345 return &cr_pub->hooks;
2346}
2347
2348static inline rb_hook_list_t *
2349rb_vm_global_hooks(const rb_execution_context_t *ec)
2350{
2351 return &rb_ec_vm_ptr(ec)->global_hooks;
2352}
2353
2354static inline rb_hook_list_t *
2355rb_ec_hooks(const rb_execution_context_t *ec, rb_event_flag_t event)
2356{
2357 // Should be a single bit set
2358 VM_ASSERT(event != 0 && ((event - 1) & event) == 0);
2359
2361 return rb_vm_global_hooks(ec);
2362 }
2363 else {
2364 return rb_ec_ractor_hooks(ec);
2365 }
2366}
2367
2368#define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \
2369 EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_hooks(ec_, flag_), flag_, self_, id_, called_id_, klass_, data_, 0)
2370
2371#define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \
2372 EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_hooks(ec_, flag_), flag_, self_, id_, called_id_, klass_, data_, 1)
2373
2374static inline void
2375rb_exec_event_hook_script_compiled(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE eval_script)
2376{
2377 EXEC_EVENT_HOOK(ec, RUBY_EVENT_SCRIPT_COMPILED, ec->cfp->self, 0, 0, 0,
2378 NIL_P(eval_script) ? (VALUE)iseq :
2379 rb_ary_new_from_args(2, eval_script, (VALUE)iseq));
2380}
2381
2382void rb_vm_trap_exit(rb_vm_t *vm);
2383void rb_vm_postponed_job_atfork(void); /* vm_trace.c */
2384void rb_vm_postponed_job_free(void); /* vm_trace.c */
2385size_t rb_vm_memsize_postponed_job_queue(void); /* vm_trace.c */
2386void rb_vm_postponed_job_queue_init(rb_vm_t *vm); /* vm_trace.c */
2387
2388RUBY_SYMBOL_EXPORT_BEGIN
2389
2390int rb_thread_check_trap_pending(void);
2391
2392/* #define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 */ /* from vm_core.h */
2393#define RUBY_EVENT_COVERAGE_LINE 0x010000
2394#define RUBY_EVENT_COVERAGE_BRANCH 0x020000
2395
2396extern VALUE rb_get_coverages(void);
2397extern void rb_set_coverages(VALUE, int, VALUE);
2398extern void rb_clear_coverages(void);
2399extern void rb_reset_coverages(void);
2400extern void rb_resume_coverages(void);
2401extern void rb_suspend_coverages(void);
2402
2403void rb_postponed_job_flush(rb_vm_t *vm);
2404
2405// ractor.c
2406RUBY_EXTERN VALUE rb_eRactorUnsafeError;
2407RUBY_EXTERN VALUE rb_eRactorIsolationError;
2408
2409RUBY_SYMBOL_EXPORT_END
2410
2411#endif /* RUBY_VM_CORE_H */
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
Definition atomic.h:69
#define RUBY_ALIGNAS
Wraps (or simulates) alignas.
Definition stdalign.h:27
#define RUBY_EXTERN
Declaration of externally visible global variables.
Definition dllexport.h:45
#define RUBY_EVENT_SCRIPT_COMPILED
Encountered an eval.
Definition event.h:60
#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK
Bitmask of GC events.
Definition event.h:100
uint32_t rb_event_flag_t
Represents event(s).
Definition event.h:108
#define RBIMPL_ATTR_FORMAT(x, y, z)
Wraps (or simulates) __attribute__((format)).
Definition format.h:29
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
Definition error.c:1398
VALUE rb_obj_is_proc(VALUE recv)
Queries if the given object is a proc.
Definition proc.c:120
void rb_unblock_function_t(void *)
This is the type of UBFs.
Definition thread.h:336
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
Definition io.h:2
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
Definition iterator.h:83
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBIMPL_ATTR_NONNULL(list)
Wraps (or simulates) __attribute__((nonnull)).
Definition nonnull.h:30
#define inline
Old Visual Studio versions do not support the inline keyword, so we need to define it to be __inline.
Definition defines.h:91
#define RARRAY_AREF(a, i)
Definition rarray.h:403
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition rtypeddata.h:103
struct rb_data_type_struct rb_data_type_t
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:205
Defines old _.
C99 shim for <stdbool.h>.
Definition vm_core.h:261
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
Definition vm_core.h:285
Definition vm_core.h:293
Definition vm_core.h:288
Definition iseq.h:259
Definition class.h:37
Definition st.h:79
IFUNC (Internal FUNCtion).
Definition imemo.h:86
Definition vm_core.h:253
Definition vm_core.h:297
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
Definition value.h:69
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40