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