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