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