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