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