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