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