Ruby 3.5.0dev (2025-06-06 revision dde9fca63bf4bf56050c734adca3eaae70506179)
vm_core.h (dde9fca63bf4bf56050c734adca3eaae70506179)
1#ifndef RUBY_VM_CORE_H
2#define RUBY_VM_CORE_H
3/**********************************************************************
4
5 vm_core.h -
6
7 $Author$
8 created at: 04/01/01 19:41:38 JST
9
10 Copyright (C) 2004-2007 Koichi Sasada
11
12**********************************************************************/
13
14/*
15 * Enable check mode.
16 * 1: enable local assertions.
17 */
18#ifndef VM_CHECK_MODE
19
20// respect RUBY_DUBUG: if given n is 0, then use RUBY_DEBUG
21#define N_OR_RUBY_DEBUG(n) (((n) > 0) ? (n) : RUBY_DEBUG)
22
23#define VM_CHECK_MODE N_OR_RUBY_DEBUG(0)
24#endif
25
39#ifndef VMDEBUG
40#define VMDEBUG 0
41#endif
42
43#if 0
44#undef VMDEBUG
45#define VMDEBUG 3
46#endif
47
48#include "ruby/internal/config.h"
49
50#include <stddef.h>
51#include <signal.h>
52#include <stdarg.h>
53
54#include "ruby_assert.h"
55
56#define RVALUE_SIZE (sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]))
57
58#if VM_CHECK_MODE > 0
59#define VM_ASSERT(expr, ...) \
60 RUBY_ASSERT_MESG_WHEN(VM_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
61#define VM_UNREACHABLE(func) rb_bug(#func ": unreachable")
62#define RUBY_ASSERT_CRITICAL_SECTION
63#define RUBY_DEBUG_THREAD_SCHEDULE() rb_thread_schedule()
64#else
65#define VM_ASSERT(/*expr, */...) ((void)0)
66#define VM_UNREACHABLE(func) UNREACHABLE
67#define RUBY_DEBUG_THREAD_SCHEDULE()
68#endif
69
70#define RUBY_ASSERT_MUTEX_OWNED(mutex) VM_ASSERT(rb_mutex_owned_p(mutex))
71
72#if defined(RUBY_ASSERT_CRITICAL_SECTION)
73/*
74# Critical Section Assertions
75
76These assertions are used to ensure that context switching does not occur between two points in the code. In theory,
77such code should already be protected by a mutex, but these assertions are used to ensure that the mutex is held.
78
79The specific case where it can be useful is where a mutex is held further up the call stack, and the code in question
80may not directly hold the mutex. In this case, the critical section assertions can be used to ensure that the mutex is
81held by someone else.
82
83These assertions are only enabled when RUBY_ASSERT_CRITICAL_SECTION is defined, which is only defined if VM_CHECK_MODE
84is set.
85
86## Example Usage
87
88```c
89RUBY_ASSERT_CRITICAL_SECTION_ENTER();
90// ... some code which does not invoke rb_vm_check_ints() ...
91RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
92```
93
94If `rb_vm_check_ints()` is called between the `RUBY_ASSERT_CRITICAL_SECTION_ENTER()` and
95`RUBY_ASSERT_CRITICAL_SECTION_LEAVE()`, a failed assertion will result.
96*/
97extern int ruby_assert_critical_section_entered;
98#define RUBY_ASSERT_CRITICAL_SECTION_ENTER() do{ruby_assert_critical_section_entered += 1;}while(false)
99#define RUBY_ASSERT_CRITICAL_SECTION_LEAVE() do{VM_ASSERT(ruby_assert_critical_section_entered > 0);ruby_assert_critical_section_entered -= 1;}while(false)
100#else
101#define RUBY_ASSERT_CRITICAL_SECTION_ENTER()
102#define RUBY_ASSERT_CRITICAL_SECTION_LEAVE()
103#endif
104
105#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
106# include "wasm/setjmp.h"
107#else
108# include <setjmp.h>
109#endif
110
111#if defined(__linux__) || defined(__FreeBSD__)
112# define RB_THREAD_T_HAS_NATIVE_ID
113#endif
114
116#include "ccan/list/list.h"
117#include "id.h"
118#include "internal.h"
119#include "internal/array.h"
120#include "internal/basic_operators.h"
121#include "internal/namespace.h"
122#include "internal/sanitizers.h"
123#include "internal/serial.h"
124#include "internal/set_table.h"
125#include "internal/vm.h"
126#include "method.h"
127#include "node.h"
128#include "ruby/ruby.h"
129#include "ruby/st.h"
130#include "ruby_atomic.h"
131#include "vm_opts.h"
132
133#include "ruby/thread_native.h"
134/*
135 * implementation selector of get_insn_info algorithm
136 * 0: linear search
137 * 1: binary search
138 * 2: succinct bitvector
139 */
140#ifndef VM_INSN_INFO_TABLE_IMPL
141# define VM_INSN_INFO_TABLE_IMPL 2
142#endif
143
144#if defined(NSIG_MAX) /* POSIX issue 8 */
145# undef NSIG
146# define NSIG NSIG_MAX
147#elif defined(_SIG_MAXSIG) /* FreeBSD */
148# undef NSIG
149# define NSIG _SIG_MAXSIG
150#elif defined(_SIGMAX) /* QNX */
151# define NSIG (_SIGMAX + 1)
152#elif defined(NSIG) /* 99% of everything else */
153# /* take it */
154#else /* Last resort */
155# define NSIG (sizeof(sigset_t) * CHAR_BIT + 1)
156#endif
157
158#define RUBY_NSIG NSIG
159
160#if defined(SIGCLD)
161# define RUBY_SIGCHLD (SIGCLD)
162#elif defined(SIGCHLD)
163# define RUBY_SIGCHLD (SIGCHLD)
164#endif
165
166#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__)
167# define USE_SIGALTSTACK
168void *rb_allocate_sigaltstack(void);
169void *rb_register_sigaltstack(void *);
170# define RB_ALTSTACK_INIT(var, altstack) var = rb_register_sigaltstack(altstack)
171# define RB_ALTSTACK_FREE(var) free(var)
172# define RB_ALTSTACK(var) var
173#else /* noop */
174# define RB_ALTSTACK_INIT(var, altstack)
175# define RB_ALTSTACK_FREE(var)
176# define RB_ALTSTACK(var) (0)
177#endif
178
179#include THREAD_IMPL_H
180#define RUBY_VM_THREAD_MODEL 2
181
182/*****************/
183/* configuration */
184/*****************/
185
186/* gcc ver. check */
187#if defined(__GNUC__) && __GNUC__ >= 2
188
189#if OPT_TOKEN_THREADED_CODE
190#if OPT_DIRECT_THREADED_CODE
191#undef OPT_DIRECT_THREADED_CODE
192#endif
193#endif
194
195#else /* defined(__GNUC__) && __GNUC__ >= 2 */
196
197/* disable threaded code options */
198#if OPT_DIRECT_THREADED_CODE
199#undef OPT_DIRECT_THREADED_CODE
200#endif
201#if OPT_TOKEN_THREADED_CODE
202#undef OPT_TOKEN_THREADED_CODE
203#endif
204#endif
205
206/* call threaded code */
207#if OPT_CALL_THREADED_CODE
208#if OPT_DIRECT_THREADED_CODE
209#undef OPT_DIRECT_THREADED_CODE
210#endif /* OPT_DIRECT_THREADED_CODE */
211#endif /* OPT_CALL_THREADED_CODE */
212
213void rb_vm_encoded_insn_data_table_init(void);
214typedef unsigned long rb_num_t;
215typedef signed long rb_snum_t;
216
217enum ruby_tag_type {
218 RUBY_TAG_NONE = 0x0,
219 RUBY_TAG_RETURN = 0x1,
220 RUBY_TAG_BREAK = 0x2,
221 RUBY_TAG_NEXT = 0x3,
222 RUBY_TAG_RETRY = 0x4,
223 RUBY_TAG_REDO = 0x5,
224 RUBY_TAG_RAISE = 0x6,
225 RUBY_TAG_THROW = 0x7,
226 RUBY_TAG_FATAL = 0x8,
227 RUBY_TAG_MASK = 0xf
228};
229
230#define TAG_NONE RUBY_TAG_NONE
231#define TAG_RETURN RUBY_TAG_RETURN
232#define TAG_BREAK RUBY_TAG_BREAK
233#define TAG_NEXT RUBY_TAG_NEXT
234#define TAG_RETRY RUBY_TAG_RETRY
235#define TAG_REDO RUBY_TAG_REDO
236#define TAG_RAISE RUBY_TAG_RAISE
237#define TAG_THROW RUBY_TAG_THROW
238#define TAG_FATAL RUBY_TAG_FATAL
239#define TAG_MASK RUBY_TAG_MASK
240
241enum ruby_vm_throw_flags {
242 VM_THROW_NO_ESCAPE_FLAG = 0x8000,
243 VM_THROW_STATE_MASK = 0xff
244};
245
246/* forward declarations */
247struct rb_thread_struct;
249
250/* iseq data type */
252
254 rb_serial_t raw;
255 VALUE data[2];
256};
257
258#define IMEMO_CONST_CACHE_SHAREABLE IMEMO_FL_USER0
259
260// imemo_constcache
262 VALUE flags;
263
264 VALUE value; // v0
265 VALUE _unused1; // v1
266 VALUE _unused2; // v2
267 const rb_cref_t *ic_cref; // v3
268};
269STATIC_ASSERT(sizeof_iseq_inline_constant_cache_entry,
270 (offsetof(struct iseq_inline_constant_cache_entry, ic_cref) +
271 sizeof(const rb_cref_t *)) <= RVALUE_SIZE);
272
289
291 uint64_t value; // dest_shape_id in former half, attr_index in latter half
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 const rb_namespace_t *proc_ns;
317};
318
319#ifndef VM_ARGC_STACK_MAX
320#define VM_ARGC_STACK_MAX 128
321#endif
322
323# define CALLING_ARGC(calling) ((calling)->heap_argv ? RARRAY_LENINT((calling)->heap_argv) : (calling)->argc)
324
326
327#if 1
328#define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj)
329#else
330#define CoreDataFromValue(obj, type) (type*)rb_data_object_get(obj)
331#endif
332#define GetCoreDataFromValue(obj, type, ptr) ((ptr) = CoreDataFromValue((obj), type))
333
335 VALUE pathobj; /* String (path) or Array [path, realpath]. Frozen. */
336 VALUE base_label; /* String */
337 VALUE label; /* String */
338 int first_lineno;
339 int node_id;
340 rb_code_location_t code_location;
342
343#define PATHOBJ_PATH 0
344#define PATHOBJ_REALPATH 1
345
346static inline VALUE
347pathobj_path(VALUE pathobj)
348{
349 if (RB_TYPE_P(pathobj, T_STRING)) {
350 return pathobj;
351 }
352 else {
353 VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY));
354 return RARRAY_AREF(pathobj, PATHOBJ_PATH);
355 }
356}
357
358static inline VALUE
359pathobj_realpath(VALUE pathobj)
360{
361 if (RB_TYPE_P(pathobj, T_STRING)) {
362 return pathobj;
363 }
364 else {
365 VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY));
366 return RARRAY_AREF(pathobj, PATHOBJ_REALPATH);
367 }
368}
369
370/* Forward declarations */
371typedef uintptr_t iseq_bits_t;
372
373#define ISEQ_IS_SIZE(body) (body->ic_size + body->ivc_size + body->ise_size + body->icvarc_size)
374
375/* [ TS_IVC | TS_ICVARC | TS_ISE | TS_IC ] */
376#define ISEQ_IS_IC_ENTRY(body, idx) (body->is_entries[(idx) + body->ise_size + body->icvarc_size + body->ivc_size].ic_cache);
377
378/* instruction sequence type */
379enum rb_iseq_type {
380 ISEQ_TYPE_TOP,
381 ISEQ_TYPE_METHOD,
382 ISEQ_TYPE_BLOCK,
383 ISEQ_TYPE_CLASS,
384 ISEQ_TYPE_RESCUE,
385 ISEQ_TYPE_ENSURE,
386 ISEQ_TYPE_EVAL,
387 ISEQ_TYPE_MAIN,
388 ISEQ_TYPE_PLAIN
389};
390
391// Attributes specified by Primitive.attr!
392enum rb_builtin_attr {
393 // The iseq does not call methods.
394 BUILTIN_ATTR_LEAF = 0x01,
395 // This iseq only contains single `opt_invokebuiltin_delegate_leave` instruction with 0 arguments.
396 BUILTIN_ATTR_SINGLE_NOARG_LEAF = 0x02,
397 // This attribute signals JIT to duplicate the iseq for each block iseq so that its `yield` will be monomorphic.
398 BUILTIN_ATTR_INLINE_BLOCK = 0x04,
399 // The iseq acts like a C method in backtraces.
400 BUILTIN_ATTR_C_TRACE = 0x08,
401};
402
403typedef VALUE (*rb_jit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *);
404
406 enum rb_iseq_type type;
407
408 unsigned int iseq_size;
409 VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */
410
434 struct {
435 struct {
436 unsigned int has_lead : 1;
437 unsigned int has_opt : 1;
438 unsigned int has_rest : 1;
439 unsigned int has_post : 1;
440 unsigned int has_kw : 1;
441 unsigned int has_kwrest : 1;
442 unsigned int has_block : 1;
443
444 unsigned int ambiguous_param0 : 1; /* {|a|} */
445 unsigned int accepts_no_kwarg : 1;
446 unsigned int ruby2_keywords: 1;
447 unsigned int anon_rest: 1;
448 unsigned int anon_kwrest: 1;
449 unsigned int use_block: 1;
450 unsigned int forwardable: 1;
451 } flags;
452
453 unsigned int size;
454
455 int lead_num;
456 int opt_num;
457 int rest_start;
458 int post_start;
459 int post_num;
460 int block_start;
461
462 const VALUE *opt_table; /* (opt_num + 1) entries. */
463 /* opt_num and opt_table:
464 *
465 * def foo o1=e1, o2=e2, ..., oN=eN
466 * #=>
467 * # prologue code
468 * A1: e1
469 * A2: e2
470 * ...
471 * AN: eN
472 * AL: body
473 * opt_num = N
474 * opt_table = [A1, A2, ..., AN, AL]
475 */
476
477 const struct rb_iseq_param_keyword {
478 int num;
479 int required_num;
480 int bits_start;
481 int rest_start;
482 const ID *table;
483 VALUE *default_values;
484 } *keyword;
486
487 rb_iseq_location_t location;
488
489 /* insn info, must be freed */
491 const struct iseq_insn_info_entry *body;
492 unsigned int *positions;
493 unsigned int size;
494#if VM_INSN_INFO_TABLE_IMPL == 2
495 struct succ_index_table *succ_index_table;
496#endif
497 } insns_info;
498
499 const ID *local_table; /* must free */
500
501 /* catch table */
502 struct iseq_catch_table *catch_table;
503
504 /* for child iseq */
505 const struct rb_iseq_struct *parent_iseq;
506 struct rb_iseq_struct *local_iseq; /* local_iseq->flip_cnt can be modified */
507
508 union iseq_inline_storage_entry *is_entries; /* [ TS_IVC | TS_ICVARC | TS_ISE | TS_IC ] */
509 struct rb_call_data *call_data; //struct rb_call_data calls[ci_size];
510
511 struct {
512 rb_snum_t flip_count;
513 VALUE script_lines;
514 VALUE coverage;
515 VALUE pc2branchindex;
516 VALUE *original_iseq;
517 } variable;
518
519 unsigned int local_table_size;
520 unsigned int ic_size; // Number of IC caches
521 unsigned int ise_size; // Number of ISE caches
522 unsigned int ivc_size; // Number of IVC caches
523 unsigned int icvarc_size; // Number of ICVARC caches
524 unsigned int ci_size;
525 unsigned int stack_max; /* for stack overflow check */
526
527 unsigned int builtin_attrs; // Union of rb_builtin_attr
528
529 bool prism; // ISEQ was generated from prism compiler
530
531 union {
532 iseq_bits_t * list; /* Find references for GC */
533 iseq_bits_t single;
534 } mark_bits;
535
536 struct rb_id_table *outer_variables;
537
538 const rb_iseq_t *mandatory_only_iseq;
539
540#if USE_YJIT || USE_ZJIT
541 // Function pointer for JIT code on jit_exec()
542 rb_jit_func_t jit_entry;
543 // Number of calls on jit_exec()
544 long unsigned jit_entry_calls;
545 // Function pointer for JIT code on jit_exec_exception()
546 rb_jit_func_t jit_exception;
547 // Number of calls on jit_exec_exception()
548 long unsigned jit_exception_calls;
549#endif
550
551#if USE_YJIT
552 // YJIT stores some data on each iseq.
553 void *yjit_payload;
554 // Used to estimate how frequently this ISEQ gets called
555 uint64_t yjit_calls_at_interv;
556#endif
557
558#if USE_ZJIT
559 // ZJIT stores some data on each iseq.
560 void *zjit_payload;
561#endif
562};
563
564/* T_IMEMO/iseq */
565/* typedef rb_iseq_t is in method.h */
567 VALUE flags; /* 1 */
568 VALUE wrapper; /* 2 */
569
570 struct rb_iseq_constant_body *body; /* 3 */
571
572 union { /* 4, 5 words */
573 struct iseq_compile_data *compile_data; /* used at compile time */
574
575 struct {
576 VALUE obj;
577 int index;
578 } loader;
579
580 struct {
581 struct rb_hook_list_struct *local_hooks;
582 rb_event_flag_t global_trace_events;
583 } exec;
584 } aux;
585};
586
587#define ISEQ_BODY(iseq) ((iseq)->body)
588
589#if !defined(USE_LAZY_LOAD) || !(USE_LAZY_LOAD+0)
590#define USE_LAZY_LOAD 0
591#endif
592
593#if !USE_LAZY_LOAD
594static inline const rb_iseq_t *rb_iseq_complete(const rb_iseq_t *iseq) {return 0;}
595#endif
596const rb_iseq_t *rb_iseq_complete(const rb_iseq_t *iseq);
597
598static inline const rb_iseq_t *
599rb_iseq_check(const rb_iseq_t *iseq)
600{
601 if (USE_LAZY_LOAD && ISEQ_BODY(iseq) == NULL) {
602 rb_iseq_complete((rb_iseq_t *)iseq);
603 }
604 return iseq;
605}
606
607static inline bool
608rb_iseq_attr_p(const rb_iseq_t *iseq, enum rb_builtin_attr attr)
609{
610 return (ISEQ_BODY(iseq)->builtin_attrs & attr) == attr;
611}
612
613static inline const rb_iseq_t *
614def_iseq_ptr(rb_method_definition_t *def)
615{
616//TODO: re-visit. to check the bug, enable this assertion.
617#if VM_CHECK_MODE > 0
618 if (def->type != VM_METHOD_TYPE_ISEQ) rb_bug("def_iseq_ptr: not iseq (%d)", def->type);
619#endif
620 return rb_iseq_check(def->body.iseq.iseqptr);
621}
622
623enum ruby_special_exceptions {
624 ruby_error_reenter,
625 ruby_error_nomemory,
626 ruby_error_sysstack,
627 ruby_error_stackfatal,
628 ruby_error_stream_closed,
629 ruby_special_error_count
630};
631
632#define GetVMPtr(obj, ptr) \
633 GetCoreDataFromValue((obj), rb_vm_t, (ptr))
634
635struct rb_vm_struct;
636typedef void rb_vm_at_exit_func(struct rb_vm_struct*);
637
638typedef struct rb_at_exit_list {
639 rb_vm_at_exit_func *func;
640 struct rb_at_exit_list *next;
642
643void *rb_objspace_alloc(void);
644void rb_objspace_free(void *objspace);
645void rb_objspace_call_finalizer(void);
646
647typedef struct rb_hook_list_struct {
648 struct rb_event_hook_struct *hooks;
649 rb_event_flag_t events;
650 unsigned int running;
651 bool need_clean;
652 bool is_local;
654
655
656// see builtin.h for definition
657typedef const struct rb_builtin_function *RB_BUILTIN;
658
660 VALUE *varptr;
661 struct global_object_list *next;
662};
663
664typedef struct rb_vm_struct {
665 VALUE self;
666
667 struct {
668 struct ccan_list_head set;
669 unsigned int cnt;
670 unsigned int blocking_cnt;
671
672 struct rb_ractor_struct *main_ractor;
673 struct rb_thread_struct *main_thread; // == vm->ractor.main_ractor->threads.main
674
675 struct {
676 // monitor
677 rb_nativethread_lock_t lock;
678 struct rb_ractor_struct *lock_owner;
679 unsigned int lock_rec;
680
681 // join at exit
682 rb_nativethread_cond_t terminate_cond;
683 bool terminate_waiting;
684
685#ifndef RUBY_THREAD_PTHREAD_H
686 // win32
687 bool barrier_waiting;
688 unsigned int barrier_cnt;
689 rb_nativethread_cond_t barrier_complete_cond;
690 rb_nativethread_cond_t barrier_release_cond;
691#endif
692 } sync;
693
694#ifdef RUBY_THREAD_PTHREAD_H
695 // ractor scheduling
696 struct {
697 rb_nativethread_lock_t lock;
698 struct rb_ractor_struct *lock_owner;
699 bool locked;
700
701 rb_nativethread_cond_t cond; // GRQ
702 unsigned int snt_cnt; // count of shared NTs
703 unsigned int dnt_cnt; // count of dedicated NTs
704
705 unsigned int running_cnt;
706
707 unsigned int max_cpu;
708 struct ccan_list_head grq; // // Global Ready Queue
709 unsigned int grq_cnt;
710
711 // running threads
712 struct ccan_list_head running_threads;
713
714 // threads which switch context by timeslice
715 struct ccan_list_head timeslice_threads;
716
717 struct ccan_list_head zombie_threads;
718
719 // true if timeslice timer is not enable
720 bool timeslice_wait_inf;
721
722 // barrier
723 rb_nativethread_cond_t barrier_complete_cond;
724 rb_nativethread_cond_t barrier_release_cond;
725 bool barrier_waiting;
726 unsigned int barrier_waiting_cnt;
727 unsigned int barrier_serial;
728 struct rb_ractor_struct *barrier_ractor;
729 unsigned int barrier_lock_rec;
730 } sched;
731#endif
732 } ractor;
733
734#ifdef USE_SIGALTSTACK
735 void *main_altstack;
736#endif
737
738 rb_serial_t fork_gen;
739
740 /* set in single-threaded processes only: */
741 volatile int ubf_async_safe;
742
743 unsigned int running: 1;
744 unsigned int thread_abort_on_exception: 1;
745 unsigned int thread_report_on_exception: 1;
746 unsigned int thread_ignore_deadlock: 1;
747
748 /* object management */
749 VALUE mark_object_ary;
751 const VALUE special_exceptions[ruby_special_error_count];
752
753 /* namespace */
754 rb_namespace_t *main_namespace;
755
756 /* load */
757 VALUE top_self;
758 VALUE load_path;
759 VALUE load_path_snapshot;
760 VALUE load_path_check_cache;
761 VALUE expanded_load_path;
762 VALUE loaded_features;
763 VALUE loaded_features_snapshot;
764 VALUE loaded_features_realpaths;
765 VALUE loaded_features_realpath_map;
766 struct st_table *loaded_features_index;
767 struct st_table *loading_table;
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 /* postponed_job (async-signal-safe, and thread-safe) */
778 struct rb_postponed_job_queue *postponed_job_queue;
779
780 int src_encoding_index;
781
782 /* workqueue (thread-safe, NOT async-signal-safe) */
783 struct ccan_list_head workqueue; /* <=> rb_workqueue_job.jnode */
784 rb_nativethread_lock_t workqueue_lock;
785
786 VALUE orig_progname, progname;
787 VALUE coverages, me2counter;
788 int coverage_mode;
789
790 struct {
791 struct rb_objspace *objspace;
792 struct gc_mark_func_data_struct {
793 void *data;
794 void (*mark_func)(VALUE v, void *data);
795 } *mark_func_data;
796 } gc;
797
798 rb_at_exit_list *at_exit;
799
800 const struct rb_builtin_function *builtin_function_table;
801
802 st_table *ci_table;
803 struct rb_id_table *negative_cme_table;
804 st_table *overloaded_cme_table; // cme -> overloaded_cme
805 set_table *unused_block_warning_table;
806
807 // This id table contains a mapping from ID to ICs. It does this with ID
808 // keys and nested st_tables as values. The nested tables have ICs as keys
809 // and Qtrue as values. It is used when inline constant caches need to be
810 // invalidated or ISEQs are being freed.
811 struct rb_id_table *constant_cache;
812 ID inserting_constant_cache_id;
813
814#ifndef VM_GLOBAL_CC_CACHE_TABLE_SIZE
815#define VM_GLOBAL_CC_CACHE_TABLE_SIZE 1023
816#endif
817 const struct rb_callcache *global_cc_cache_table[VM_GLOBAL_CC_CACHE_TABLE_SIZE]; // vm_eval.c
818
819#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
820 uint32_t clock;
821#endif
822
823 /* params */
824 struct { /* size in byte */
825 size_t thread_vm_stack_size;
826 size_t thread_machine_stack_size;
827 size_t fiber_vm_stack_size;
828 size_t fiber_machine_stack_size;
829 } default_params;
830
831 // TODO: a single require_stack can't support multi-threaded require trees
832 VALUE require_stack;
833} rb_vm_t;
834
835/* default values */
836
837#define RUBY_VM_SIZE_ALIGN 4096
838
839#define RUBY_VM_THREAD_VM_STACK_SIZE ( 128 * 1024 * sizeof(VALUE)) /* 512 KB or 1024 KB */
840#define RUBY_VM_THREAD_VM_STACK_SIZE_MIN ( 2 * 1024 * sizeof(VALUE)) /* 8 KB or 16 KB */
841#define RUBY_VM_THREAD_MACHINE_STACK_SIZE ( 128 * 1024 * sizeof(VALUE)) /* 512 KB or 1024 KB */
842#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
843
844#define RUBY_VM_FIBER_VM_STACK_SIZE ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
845#define RUBY_VM_FIBER_VM_STACK_SIZE_MIN ( 2 * 1024 * sizeof(VALUE)) /* 8 KB or 16 KB */
846#define RUBY_VM_FIBER_MACHINE_STACK_SIZE ( 64 * 1024 * sizeof(VALUE)) /* 256 KB or 512 KB */
847#if defined(__powerpc64__) || defined(__ppc64__) // macOS has __ppc64__
848#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 32 * 1024 * sizeof(VALUE)) /* 128 KB or 256 KB */
849#else
850#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 16 * 1024 * sizeof(VALUE)) /* 64 KB or 128 KB */
851#endif
852
853#if __has_feature(memory_sanitizer) || __has_feature(address_sanitizer)
854/* It seems sanitizers consume A LOT of machine stacks */
855#undef RUBY_VM_THREAD_MACHINE_STACK_SIZE
856#define RUBY_VM_THREAD_MACHINE_STACK_SIZE (1024 * 1024 * sizeof(VALUE))
857#undef RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
858#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN ( 512 * 1024 * sizeof(VALUE))
859#undef RUBY_VM_FIBER_MACHINE_STACK_SIZE
860#define RUBY_VM_FIBER_MACHINE_STACK_SIZE ( 256 * 1024 * sizeof(VALUE))
861#undef RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
862#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN ( 128 * 1024 * sizeof(VALUE))
863#endif
864
865#ifndef VM_DEBUG_BP_CHECK
866#define VM_DEBUG_BP_CHECK 0
867#endif
868
869#ifndef VM_DEBUG_VERIFY_METHOD_CACHE
870#define VM_DEBUG_VERIFY_METHOD_CACHE (VMDEBUG != 0)
871#endif
872
874 VALUE self;
875 const VALUE *ep;
876 union {
877 const rb_iseq_t *iseq;
878 const struct vm_ifunc *ifunc;
879 VALUE val;
880 } code;
881};
882
883enum rb_block_handler_type {
884 block_handler_type_iseq,
885 block_handler_type_ifunc,
886 block_handler_type_symbol,
887 block_handler_type_proc
888};
889
890enum rb_block_type {
891 block_type_iseq,
892 block_type_ifunc,
893 block_type_symbol,
894 block_type_proc
895};
896
897struct rb_block {
898 union {
899 struct rb_captured_block captured;
900 VALUE symbol;
901 VALUE proc;
902 } as;
903 enum rb_block_type type;
904};
905
907 const VALUE *pc; // cfp[0]
908 VALUE *sp; // cfp[1]
909 const rb_iseq_t *iseq; // cfp[2]
910 VALUE self; // cfp[3] / block[0]
911 const VALUE *ep; // cfp[4] / block[1]
912 const void *block_code; // cfp[5] / block[2] -- iseq, ifunc, or forwarded block handler
913 void *jit_return; // cfp[6] -- return address for JIT code
914#if VM_DEBUG_BP_CHECK
915 VALUE *bp_check; // cfp[7]
916#endif
918
919extern const rb_data_type_t ruby_threadptr_data_type;
920
921static inline struct rb_thread_struct *
922rb_thread_ptr(VALUE thval)
923{
924 return (struct rb_thread_struct *)rb_check_typeddata(thval, &ruby_threadptr_data_type);
925}
926
927enum rb_thread_status {
928 THREAD_RUNNABLE,
929 THREAD_STOPPED,
930 THREAD_STOPPED_FOREVER,
931 THREAD_KILLED
932};
933
934#ifdef RUBY_JMP_BUF
935typedef RUBY_JMP_BUF rb_jmpbuf_t;
936#else
937typedef void *rb_jmpbuf_t[5];
938#endif
939
940/*
941 `rb_vm_tag_jmpbuf_t` type represents a buffer used to
942 long jump to a C frame associated with `rb_vm_tag`.
943
944 Use-site of `rb_vm_tag_jmpbuf_t` is responsible for calling the
945 following functions:
946 - `rb_vm_tag_jmpbuf_init` once `rb_vm_tag_jmpbuf_t` is allocated.
947 - `rb_vm_tag_jmpbuf_deinit` once `rb_vm_tag_jmpbuf_t` is no longer necessary.
948
949 `RB_VM_TAG_JMPBUF_GET` transforms a `rb_vm_tag_jmpbuf_t` into a
950 `rb_jmpbuf_t` to be passed to `rb_setjmp/rb_longjmp`.
951*/
952#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
953/*
954 WebAssembly target with Asyncify-based SJLJ needs
955 to capture the execution context by unwind/rewind-ing
956 call frames into a jump buffer. The buffer space tends
957 to be considerably large unlike other architectures'
958 register-based buffers.
959 Therefore, we allocates the buffer on the heap on such
960 environments.
961*/
962typedef rb_jmpbuf_t *rb_vm_tag_jmpbuf_t;
963
964#define RB_VM_TAG_JMPBUF_GET(buf) (*buf)
965
966static inline void
967rb_vm_tag_jmpbuf_init(rb_vm_tag_jmpbuf_t *jmpbuf)
968{
969 *jmpbuf = ruby_xmalloc(sizeof(rb_jmpbuf_t));
970}
971
972static inline void
973rb_vm_tag_jmpbuf_deinit(const rb_vm_tag_jmpbuf_t *jmpbuf)
974{
975 ruby_xfree(*jmpbuf);
976}
977#else
978typedef rb_jmpbuf_t rb_vm_tag_jmpbuf_t;
979
980#define RB_VM_TAG_JMPBUF_GET(buf) (buf)
981
982static inline void
983rb_vm_tag_jmpbuf_init(rb_vm_tag_jmpbuf_t *jmpbuf)
984{
985 // no-op
986}
987
988static inline void
989rb_vm_tag_jmpbuf_deinit(const rb_vm_tag_jmpbuf_t *jmpbuf)
990{
991 // no-op
992}
993#endif
994
995/*
996 the members which are written in EC_PUSH_TAG() should be placed at
997 the beginning and the end, so that entire region is accessible.
998*/
999struct rb_vm_tag {
1000 VALUE tag;
1001 VALUE retval;
1002 rb_vm_tag_jmpbuf_t buf;
1003 struct rb_vm_tag *prev;
1004 enum ruby_tag_type state;
1005 unsigned int lock_rec;
1006};
1007
1008STATIC_ASSERT(rb_vm_tag_buf_offset, offsetof(struct rb_vm_tag, buf) > 0);
1009STATIC_ASSERT(rb_vm_tag_buf_end,
1010 offsetof(struct rb_vm_tag, buf) + sizeof(rb_vm_tag_jmpbuf_t) <
1011 sizeof(struct rb_vm_tag));
1012
1015 void *arg;
1016};
1017
1018struct rb_mutex_struct;
1019
1020typedef struct rb_fiber_struct rb_fiber_t;
1021
1023 struct rb_waiting_list *next;
1024 struct rb_thread_struct *thread;
1025 struct rb_fiber_struct *fiber;
1026};
1027
1029 /* execution information */
1030 VALUE *vm_stack; /* must free, must mark */
1031 size_t vm_stack_size; /* size in word (byte size / sizeof(VALUE)) */
1032 rb_control_frame_t *cfp;
1033
1034 struct rb_vm_tag *tag;
1035
1036 /* interrupt flags */
1037 rb_atomic_t interrupt_flag;
1038 rb_atomic_t interrupt_mask; /* size should match flag */
1039#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
1040 uint32_t checked_clock;
1041#endif
1042
1043 rb_fiber_t *fiber_ptr;
1044 struct rb_thread_struct *thread_ptr;
1045
1046 /* storage (ec (fiber) local) */
1047 struct rb_id_table *local_storage;
1048 VALUE local_storage_recursive_hash;
1049 VALUE local_storage_recursive_hash_for_trace;
1050
1051 /* Inheritable fiber storage. */
1052 VALUE storage;
1053
1054 /* eval env */
1055 const VALUE *root_lep;
1056 VALUE root_svar;
1057
1058 /* trace information */
1059 struct rb_trace_arg_struct *trace_arg;
1060
1061 /* temporary places */
1062 VALUE errinfo;
1063 VALUE passed_block_handler; /* for rb_iterate */
1064
1065 uint8_t raised_flag; /* only 3 bits needed */
1066
1067 /* n.b. only 7 bits needed, really: */
1068 BITFIELD(enum method_missing_reason, method_missing_reason, 8);
1069
1070 VALUE private_const_reference;
1071
1072 /* for GC */
1073 struct {
1074 VALUE *stack_start;
1075 VALUE *stack_end;
1076 size_t stack_maxsize;
1078
1079#ifdef RUBY_ASAN_ENABLED
1080 void *asan_fake_stack_handle;
1081#endif
1082 } machine;
1083};
1084
1085#ifndef rb_execution_context_t
1087#define rb_execution_context_t rb_execution_context_t
1088#endif
1089
1090// for builtin.h
1091#define VM_CORE_H_EC_DEFINED 1
1092
1093// Set the vm_stack pointer in the execution context.
1094void rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
1095
1096// Initialize the vm_stack pointer in the execution context and push the initial stack frame.
1097// @param ec the execution context to update.
1098// @param stack a pointer to the stack to use.
1099// @param size the size of the stack, as in `VALUE stack[size]`.
1100void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
1101
1102// Clear (set to `NULL`) the vm_stack pointer.
1103// @param ec the execution context to update.
1104void rb_ec_clear_vm_stack(rb_execution_context_t *ec);
1105
1107 bool ractor_safe;
1108};
1109
1110typedef struct rb_ractor_struct rb_ractor_t;
1111
1112struct rb_native_thread;
1113
1114typedef struct rb_thread_struct {
1115 struct ccan_list_node lt_node; // managed by a ractor (r->threads.set)
1116 VALUE self;
1117 rb_ractor_t *ractor;
1118 rb_vm_t *vm;
1119 struct rb_native_thread *nt;
1121
1122 struct rb_thread_sched_item sched;
1123 bool mn_schedulable;
1124 rb_atomic_t serial; // only for RUBY_DEBUG_LOG()
1125
1126 VALUE last_status; /* $? */
1127
1128 /* for cfunc */
1129 struct rb_calling_info *calling;
1130
1131 /* for load(true) */
1132 VALUE top_self;
1133 VALUE top_wrapper;
1134 /* for namespace */
1135 VALUE namespaces; // Stack of namespaces
1136 rb_namespace_t *ns; // The current one
1137
1138 /* thread control */
1139
1140 BITFIELD(enum rb_thread_status, status, 2);
1141 /* bit flags */
1142 unsigned int has_dedicated_nt : 1;
1143 unsigned int to_kill : 1;
1144 unsigned int abort_on_exception: 1;
1145 unsigned int report_on_exception: 1;
1146 unsigned int pending_interrupt_queue_checked: 1;
1147 int8_t priority; /* -3 .. 3 (RUBY_THREAD_PRIORITY_{MIN,MAX}) */
1148 uint32_t running_time_us; /* 12500..800000 */
1149
1150 void *blocking_region_buffer;
1151
1152 VALUE thgroup;
1153 VALUE value;
1154
1155 /* temporary place of retval on OPT_CALL_THREADED_CODE */
1156#if OPT_CALL_THREADED_CODE
1157 VALUE retval;
1158#endif
1159
1160 /* async errinfo queue */
1161 VALUE pending_interrupt_queue;
1162 VALUE pending_interrupt_mask_stack;
1163
1164 /* interrupt management */
1165 rb_nativethread_lock_t interrupt_lock;
1166 struct rb_unblock_callback unblock;
1167 VALUE locking_mutex;
1168 struct rb_mutex_struct *keeping_mutexes;
1169 struct ccan_list_head interrupt_exec_tasks;
1170
1171 struct rb_waiting_list *join_list;
1172
1173 union {
1174 struct {
1175 VALUE proc;
1176 VALUE args;
1177 int kw_splat;
1178 } proc;
1179 struct {
1180 VALUE (*func)(void *);
1181 void *arg;
1182 } func;
1183 } invoke_arg;
1184
1185 enum thread_invoke_type {
1186 thread_invoke_type_none = 0,
1187 thread_invoke_type_proc,
1188 thread_invoke_type_ractor_proc,
1189 thread_invoke_type_func
1190 } invoke_type;
1191
1192 /* fiber */
1193 rb_fiber_t *root_fiber;
1194
1195 VALUE scheduler;
1196 unsigned int blocking;
1197
1198 /* misc */
1199 VALUE name;
1200 void **specific_storage;
1201
1202 struct rb_ext_config ext_config;
1203} rb_thread_t;
1204
1205static inline unsigned int
1206rb_th_serial(const rb_thread_t *th)
1207{
1208 return th ? (unsigned int)th->serial : 0;
1209}
1210
1211typedef enum {
1212 VM_DEFINECLASS_TYPE_CLASS = 0x00,
1213 VM_DEFINECLASS_TYPE_SINGLETON_CLASS = 0x01,
1214 VM_DEFINECLASS_TYPE_MODULE = 0x02,
1215 /* 0x03..0x06 is reserved */
1216 VM_DEFINECLASS_TYPE_MASK = 0x07
1217} rb_vm_defineclass_type_t;
1218
1219#define VM_DEFINECLASS_TYPE(x) ((rb_vm_defineclass_type_t)(x) & VM_DEFINECLASS_TYPE_MASK)
1220#define VM_DEFINECLASS_FLAG_SCOPED 0x08
1221#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS 0x10
1222#define VM_DEFINECLASS_SCOPED_P(x) ((x) & VM_DEFINECLASS_FLAG_SCOPED)
1223#define VM_DEFINECLASS_HAS_SUPERCLASS_P(x) \
1224 ((x) & VM_DEFINECLASS_FLAG_HAS_SUPERCLASS)
1225
1226/* iseq.c */
1227RUBY_SYMBOL_EXPORT_BEGIN
1228
1229/* node -> iseq */
1230rb_iseq_t *rb_iseq_new (const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type);
1231rb_iseq_t *rb_iseq_new_top (const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
1232rb_iseq_t *rb_iseq_new_main (const VALUE ast_value, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt);
1233rb_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);
1234rb_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,
1235 enum rb_iseq_type, const rb_compile_option_t*,
1236 VALUE script_lines);
1237
1238struct iseq_link_anchor;
1240 VALUE flags;
1241 VALUE reserved;
1242 void (*func)(rb_iseq_t *, struct iseq_link_anchor *, const void *);
1243 const void *data;
1244};
1245static inline struct rb_iseq_new_with_callback_callback_func *
1246rb_iseq_new_with_callback_new_callback(
1247 void (*func)(rb_iseq_t *, struct iseq_link_anchor *, const void *), const void *ptr)
1248{
1250 IMEMO_NEW(struct rb_iseq_new_with_callback_callback_func, imemo_ifunc, Qfalse);
1251 memo->func = func;
1252 memo->data = ptr;
1253
1254 return memo;
1255}
1256rb_iseq_t *rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_callback_func * ifunc,
1257 VALUE name, VALUE path, VALUE realpath, int first_lineno,
1258 const rb_iseq_t *parent, enum rb_iseq_type, const rb_compile_option_t*);
1259
1260VALUE rb_iseq_disasm(const rb_iseq_t *iseq);
1261int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child);
1262
1263VALUE rb_iseq_coverage(const rb_iseq_t *iseq);
1264
1265RUBY_EXTERN VALUE rb_cISeq;
1266RUBY_EXTERN VALUE rb_cRubyVM;
1267RUBY_EXTERN VALUE rb_mRubyVMFrozenCore;
1268RUBY_EXTERN VALUE rb_block_param_proxy;
1269RUBY_SYMBOL_EXPORT_END
1270
1271#define GetProcPtr(obj, ptr) \
1272 GetCoreDataFromValue((obj), rb_proc_t, (ptr))
1273
1274typedef struct {
1275 const struct rb_block block;
1276 const rb_namespace_t *ns;
1277 unsigned int is_from_method: 1; /* bool */
1278 unsigned int is_lambda: 1; /* bool */
1279 unsigned int is_isolated: 1; /* bool */
1280} rb_proc_t;
1281
1282RUBY_SYMBOL_EXPORT_BEGIN
1283VALUE rb_proc_isolate(VALUE self);
1284VALUE rb_proc_isolate_bang(VALUE self);
1285VALUE rb_proc_ractor_make_shareable(VALUE self);
1286RUBY_SYMBOL_EXPORT_END
1287
1288typedef struct {
1289 VALUE flags; /* imemo header */
1290 rb_iseq_t *iseq;
1291 const VALUE *ep;
1292 const VALUE *env;
1293 unsigned int env_size;
1294} rb_env_t;
1295
1296extern const rb_data_type_t ruby_binding_data_type;
1297
1298#define GetBindingPtr(obj, ptr) \
1299 GetCoreDataFromValue((obj), rb_binding_t, (ptr))
1300
1301typedef struct {
1302 const struct rb_block block;
1303 const VALUE pathobj;
1304 int first_lineno;
1305} rb_binding_t;
1306
1307/* used by compile time and send insn */
1308
1309enum vm_check_match_type {
1310 VM_CHECKMATCH_TYPE_WHEN = 1,
1311 VM_CHECKMATCH_TYPE_CASE = 2,
1312 VM_CHECKMATCH_TYPE_RESCUE = 3
1313};
1314
1315#define VM_CHECKMATCH_TYPE_MASK 0x03
1316#define VM_CHECKMATCH_ARRAY 0x04
1317
1318enum vm_opt_newarray_send_type {
1319 VM_OPT_NEWARRAY_SEND_MAX = 1,
1320 VM_OPT_NEWARRAY_SEND_MIN = 2,
1321 VM_OPT_NEWARRAY_SEND_HASH = 3,
1322 VM_OPT_NEWARRAY_SEND_PACK = 4,
1323 VM_OPT_NEWARRAY_SEND_PACK_BUFFER = 5,
1324 VM_OPT_NEWARRAY_SEND_INCLUDE_P = 6,
1325};
1326
1327enum vm_special_object_type {
1328 VM_SPECIAL_OBJECT_VMCORE = 1,
1329 VM_SPECIAL_OBJECT_CBASE,
1330 VM_SPECIAL_OBJECT_CONST_BASE
1331};
1332
1333enum vm_svar_index {
1334 VM_SVAR_LASTLINE = 0, /* $_ */
1335 VM_SVAR_BACKREF = 1, /* $~ */
1336
1337 VM_SVAR_EXTRA_START = 2,
1338 VM_SVAR_FLIPFLOP_START = 2 /* flipflop */
1339};
1340
1341/* inline cache */
1342typedef struct iseq_inline_constant_cache *IC;
1343typedef struct iseq_inline_iv_cache_entry *IVC;
1344typedef struct iseq_inline_cvar_cache_entry *ICVARC;
1345typedef union iseq_inline_storage_entry *ISE;
1346typedef const struct rb_callinfo *CALL_INFO;
1347typedef const struct rb_callcache *CALL_CACHE;
1348typedef struct rb_call_data *CALL_DATA;
1349
1350typedef VALUE CDHASH;
1351
1352#ifndef FUNC_FASTCALL
1353#define FUNC_FASTCALL(x) x
1354#endif
1355
1356typedef rb_control_frame_t *
1357 (FUNC_FASTCALL(*rb_insn_func_t))(rb_execution_context_t *, rb_control_frame_t *);
1358
1359#define VM_TAGGED_PTR_SET(p, tag) ((VALUE)(p) | (tag))
1360#define VM_TAGGED_PTR_REF(v, mask) ((void *)((v) & ~mask))
1361
1362#define GC_GUARDED_PTR(p) VM_TAGGED_PTR_SET((p), 0x01)
1363#define GC_GUARDED_PTR_REF(p) VM_TAGGED_PTR_REF((p), 0x03)
1364#define GC_GUARDED_PTR_P(p) (((VALUE)(p)) & 0x01)
1365
1366enum vm_frame_env_flags {
1367 /* Frame/Environment flag bits:
1368 * MMMM MMMM MMMM MMMM __FF FFFF FFFE EEEX (LSB)
1369 *
1370 * X : tag for GC marking (It seems as Fixnum)
1371 * EEE : 4 bits Env flags
1372 * FF..: 9 bits Frame flags
1373 * MM..: 15 bits frame magic (to check frame corruption)
1374 */
1375
1376 /* frame types */
1377 VM_FRAME_MAGIC_METHOD = 0x11110001,
1378 VM_FRAME_MAGIC_BLOCK = 0x22220001,
1379 VM_FRAME_MAGIC_CLASS = 0x33330001,
1380 VM_FRAME_MAGIC_TOP = 0x44440001,
1381 VM_FRAME_MAGIC_CFUNC = 0x55550001,
1382 VM_FRAME_MAGIC_IFUNC = 0x66660001,
1383 VM_FRAME_MAGIC_EVAL = 0x77770001,
1384 VM_FRAME_MAGIC_RESCUE = 0x78880001,
1385 VM_FRAME_MAGIC_DUMMY = 0x79990001,
1386
1387 VM_FRAME_MAGIC_MASK = 0x7fff0001,
1388
1389 /* frame flag */
1390 VM_FRAME_FLAG_FINISH = 0x0020,
1391 VM_FRAME_FLAG_BMETHOD = 0x0040,
1392 VM_FRAME_FLAG_CFRAME = 0x0080,
1393 VM_FRAME_FLAG_LAMBDA = 0x0100,
1394 VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200,
1395 VM_FRAME_FLAG_CFRAME_KW = 0x0400,
1396 VM_FRAME_FLAG_PASSED = 0x0800,
1397 VM_FRAME_FLAG_NS_SWITCH = 0x1000,
1398 VM_FRAME_FLAG_LOAD_ISEQ = 0x2000,
1399
1400 /* env flag */
1401 VM_ENV_FLAG_LOCAL = 0x0002,
1402 VM_ENV_FLAG_ESCAPED = 0x0004,
1403 VM_ENV_FLAG_WB_REQUIRED = 0x0008,
1404 VM_ENV_FLAG_ISOLATED = 0x0010,
1405};
1406
1407#define VM_ENV_DATA_SIZE ( 3)
1408
1409#define VM_ENV_DATA_INDEX_ME_CREF (-2) /* ep[-2] */
1410#define VM_ENV_DATA_INDEX_SPECVAL (-1) /* ep[-1] */
1411#define VM_ENV_DATA_INDEX_FLAGS ( 0) /* ep[ 0] */
1412#define VM_ENV_DATA_INDEX_ENV ( 1) /* ep[ 1] */
1413
1414#define VM_ENV_INDEX_LAST_LVAR (-VM_ENV_DATA_SIZE)
1415
1416static inline void VM_FORCE_WRITE_SPECIAL_CONST(const VALUE *ptr, VALUE special_const_value);
1417
1418static inline void
1419VM_ENV_FLAGS_SET(const VALUE *ep, VALUE flag)
1420{
1421 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1422 VM_ASSERT(FIXNUM_P(flags));
1423 VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags | flag);
1424}
1425
1426static inline void
1427VM_ENV_FLAGS_UNSET(const VALUE *ep, VALUE flag)
1428{
1429 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1430 VM_ASSERT(FIXNUM_P(flags));
1431 VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags & ~flag);
1432}
1433
1434static inline unsigned long
1435VM_ENV_FLAGS(const VALUE *ep, long flag)
1436{
1437 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1438 VM_ASSERT(FIXNUM_P(flags));
1439 return flags & flag;
1440}
1441
1442static inline unsigned long
1443VM_FRAME_TYPE(const rb_control_frame_t *cfp)
1444{
1445 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_MAGIC_MASK);
1446}
1447
1448static inline int
1449VM_FRAME_LAMBDA_P(const rb_control_frame_t *cfp)
1450{
1451 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_LAMBDA) != 0;
1452}
1453
1454static inline int
1455VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp)
1456{
1457 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0;
1458}
1459
1460static inline int
1461VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp)
1462{
1463 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_FINISH) != 0;
1464}
1465
1466static inline int
1467VM_FRAME_BMETHOD_P(const rb_control_frame_t *cfp)
1468{
1469 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_BMETHOD) != 0;
1470}
1471
1472static inline int
1473rb_obj_is_iseq(VALUE iseq)
1474{
1475 return imemo_type_p(iseq, imemo_iseq);
1476}
1477
1478#if VM_CHECK_MODE > 0
1479#define RUBY_VM_NORMAL_ISEQ_P(iseq) rb_obj_is_iseq((VALUE)iseq)
1480#endif
1481
1482static inline int
1483VM_FRAME_CFRAME_P(const rb_control_frame_t *cfp)
1484{
1485 int cframe_p = VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME) != 0;
1486 VM_ASSERT(RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) != cframe_p ||
1487 (VM_FRAME_TYPE(cfp) & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY);
1488 return cframe_p;
1489}
1490
1491static inline int
1492VM_FRAME_RUBYFRAME_P(const rb_control_frame_t *cfp)
1493{
1494 return !VM_FRAME_CFRAME_P(cfp);
1495}
1496
1497static inline int
1498VM_FRAME_NS_SWITCH_P(const rb_control_frame_t *cfp)
1499{
1500 return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_NS_SWITCH) != 0;
1501}
1502
1503#define RUBYVM_CFUNC_FRAME_P(cfp) \
1504 (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
1505
1506#define VM_GUARDED_PREV_EP(ep) GC_GUARDED_PTR(ep)
1507#define VM_BLOCK_HANDLER_NONE 0
1508
1509static inline int
1510VM_ENV_LOCAL_P(const VALUE *ep)
1511{
1512 return VM_ENV_FLAGS(ep, VM_ENV_FLAG_LOCAL) ? 1 : 0;
1513}
1514
1515static inline const VALUE *
1516VM_ENV_PREV_EP(const VALUE *ep)
1517{
1518 VM_ASSERT(VM_ENV_LOCAL_P(ep) == 0);
1519 return GC_GUARDED_PTR_REF(ep[VM_ENV_DATA_INDEX_SPECVAL]);
1520}
1521
1522static inline VALUE
1523VM_ENV_BLOCK_HANDLER(const VALUE *ep)
1524{
1525 VM_ASSERT(VM_ENV_LOCAL_P(ep));
1526 return ep[VM_ENV_DATA_INDEX_SPECVAL];
1527}
1528
1529#if VM_CHECK_MODE > 0
1530int rb_vm_ep_in_heap_p(const VALUE *ep);
1531#endif
1532
1533static inline int
1534VM_ENV_ESCAPED_P(const VALUE *ep)
1535{
1536 VM_ASSERT(rb_vm_ep_in_heap_p(ep) == !!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED));
1537 return VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) ? 1 : 0;
1538}
1539
1541static inline VALUE
1542VM_ENV_ENVVAL(const VALUE *ep)
1543{
1544 VALUE envval = ep[VM_ENV_DATA_INDEX_ENV];
1545 VM_ASSERT(VM_ENV_ESCAPED_P(ep));
1546 VM_ASSERT(envval == Qundef || imemo_type_p(envval, imemo_env));
1547 return envval;
1548}
1549
1551static inline const rb_env_t *
1552VM_ENV_ENVVAL_PTR(const VALUE *ep)
1553{
1554 return (const rb_env_t *)VM_ENV_ENVVAL(ep);
1555}
1556
1557static inline const rb_env_t *
1558vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq)
1559{
1560 rb_env_t *env = IMEMO_NEW(rb_env_t, imemo_env, (VALUE)iseq);
1561 env->ep = env_ep;
1562 env->env = env_body;
1563 env->env_size = env_size;
1564 env_ep[VM_ENV_DATA_INDEX_ENV] = (VALUE)env;
1565 return env;
1566}
1567
1568static inline void
1569VM_FORCE_WRITE(const VALUE *ptr, VALUE v)
1570{
1571 *((VALUE *)ptr) = v;
1572}
1573
1574static inline void
1575VM_FORCE_WRITE_SPECIAL_CONST(const VALUE *ptr, VALUE special_const_value)
1576{
1577 VM_ASSERT(RB_SPECIAL_CONST_P(special_const_value));
1578 VM_FORCE_WRITE(ptr, special_const_value);
1579}
1580
1581static inline void
1582VM_STACK_ENV_WRITE(const VALUE *ep, int index, VALUE v)
1583{
1584 VM_ASSERT(VM_ENV_FLAGS(ep, VM_ENV_FLAG_WB_REQUIRED) == 0);
1585 VM_FORCE_WRITE(&ep[index], v);
1586}
1587
1588const VALUE *rb_vm_ep_local_ep(const VALUE *ep);
1589const VALUE *rb_vm_proc_local_ep(VALUE proc);
1590void rb_vm_block_ep_update(VALUE obj, const struct rb_block *dst, const VALUE *ep);
1591void rb_vm_block_copy(VALUE obj, const struct rb_block *dst, const struct rb_block *src);
1592
1593VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp);
1594
1595#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ((cfp)+1)
1596#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) ((cfp)-1)
1597
1598#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \
1599 ((void *)(ecfp) > (void *)(cfp))
1600
1601static inline const rb_control_frame_t *
1602RUBY_VM_END_CONTROL_FRAME(const rb_execution_context_t *ec)
1603{
1604 return (rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size);
1605}
1606
1607static inline int
1608RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
1609{
1610 return !RUBY_VM_VALID_CONTROL_FRAME_P(cfp, RUBY_VM_END_CONTROL_FRAME(ec));
1611}
1612
1613static inline int
1614VM_BH_ISEQ_BLOCK_P(VALUE block_handler)
1615{
1616 if ((block_handler & 0x03) == 0x01) {
1617#if VM_CHECK_MODE > 0
1618 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1619 VM_ASSERT(imemo_type_p(captured->code.val, imemo_iseq));
1620#endif
1621 return 1;
1622 }
1623 else {
1624 return 0;
1625 }
1626}
1627
1628static inline VALUE
1629VM_BH_FROM_ISEQ_BLOCK(const struct rb_captured_block *captured)
1630{
1631 VALUE block_handler = VM_TAGGED_PTR_SET(captured, 0x01);
1632 VM_ASSERT(VM_BH_ISEQ_BLOCK_P(block_handler));
1633 return block_handler;
1634}
1635
1636static inline const struct rb_captured_block *
1637VM_BH_TO_ISEQ_BLOCK(VALUE block_handler)
1638{
1639 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1640 VM_ASSERT(VM_BH_ISEQ_BLOCK_P(block_handler));
1641 return captured;
1642}
1643
1644static inline int
1645VM_BH_IFUNC_P(VALUE block_handler)
1646{
1647 if ((block_handler & 0x03) == 0x03) {
1648#if VM_CHECK_MODE > 0
1649 struct rb_captured_block *captured = (void *)(block_handler & ~0x03);
1650 VM_ASSERT(imemo_type_p(captured->code.val, imemo_ifunc));
1651#endif
1652 return 1;
1653 }
1654 else {
1655 return 0;
1656 }
1657}
1658
1659static inline VALUE
1660VM_BH_FROM_IFUNC_BLOCK(const struct rb_captured_block *captured)
1661{
1662 VALUE block_handler = VM_TAGGED_PTR_SET(captured, 0x03);
1663 VM_ASSERT(VM_BH_IFUNC_P(block_handler));
1664 return block_handler;
1665}
1666
1667static inline const struct rb_captured_block *
1668VM_BH_TO_IFUNC_BLOCK(VALUE block_handler)
1669{
1670 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1671 VM_ASSERT(VM_BH_IFUNC_P(block_handler));
1672 return captured;
1673}
1674
1675static inline const struct rb_captured_block *
1676VM_BH_TO_CAPT_BLOCK(VALUE block_handler)
1677{
1678 struct rb_captured_block *captured = VM_TAGGED_PTR_REF(block_handler, 0x03);
1679 VM_ASSERT(VM_BH_IFUNC_P(block_handler) || VM_BH_ISEQ_BLOCK_P(block_handler));
1680 return captured;
1681}
1682
1683static inline enum rb_block_handler_type
1684vm_block_handler_type(VALUE block_handler)
1685{
1686 if (VM_BH_ISEQ_BLOCK_P(block_handler)) {
1687 return block_handler_type_iseq;
1688 }
1689 else if (VM_BH_IFUNC_P(block_handler)) {
1690 return block_handler_type_ifunc;
1691 }
1692 else if (SYMBOL_P(block_handler)) {
1693 return block_handler_type_symbol;
1694 }
1695 else {
1696 VM_ASSERT(rb_obj_is_proc(block_handler));
1697 return block_handler_type_proc;
1698 }
1699}
1700
1701static inline void
1702vm_block_handler_verify(MAYBE_UNUSED(VALUE block_handler))
1703{
1704 VM_ASSERT(block_handler == VM_BLOCK_HANDLER_NONE ||
1705 (vm_block_handler_type(block_handler), 1));
1706}
1707
1708static inline enum rb_block_type
1709vm_block_type(const struct rb_block *block)
1710{
1711#if VM_CHECK_MODE > 0
1712 switch (block->type) {
1713 case block_type_iseq:
1714 VM_ASSERT(imemo_type_p(block->as.captured.code.val, imemo_iseq));
1715 break;
1716 case block_type_ifunc:
1717 VM_ASSERT(imemo_type_p(block->as.captured.code.val, imemo_ifunc));
1718 break;
1719 case block_type_symbol:
1720 VM_ASSERT(SYMBOL_P(block->as.symbol));
1721 break;
1722 case block_type_proc:
1723 VM_ASSERT(rb_obj_is_proc(block->as.proc));
1724 break;
1725 }
1726#endif
1727 return block->type;
1728}
1729
1730static inline void
1731vm_block_type_set(const struct rb_block *block, enum rb_block_type type)
1732{
1733 struct rb_block *mb = (struct rb_block *)block;
1734 mb->type = type;
1735}
1736
1737static inline const struct rb_block *
1738vm_proc_block(VALUE procval)
1739{
1740 VM_ASSERT(rb_obj_is_proc(procval));
1741 return &((rb_proc_t *)RTYPEDDATA_DATA(procval))->block;
1742}
1743
1744static inline const rb_iseq_t *vm_block_iseq(const struct rb_block *block);
1745static inline const VALUE *vm_block_ep(const struct rb_block *block);
1746
1747static inline const rb_iseq_t *
1748vm_proc_iseq(VALUE procval)
1749{
1750 return vm_block_iseq(vm_proc_block(procval));
1751}
1752
1753static inline const VALUE *
1754vm_proc_ep(VALUE procval)
1755{
1756 return vm_block_ep(vm_proc_block(procval));
1757}
1758
1759static inline const rb_iseq_t *
1760vm_block_iseq(const struct rb_block *block)
1761{
1762 switch (vm_block_type(block)) {
1763 case block_type_iseq: return rb_iseq_check(block->as.captured.code.iseq);
1764 case block_type_proc: return vm_proc_iseq(block->as.proc);
1765 case block_type_ifunc:
1766 case block_type_symbol: return NULL;
1767 }
1768 VM_UNREACHABLE(vm_block_iseq);
1769 return NULL;
1770}
1771
1772static inline const VALUE *
1773vm_block_ep(const struct rb_block *block)
1774{
1775 switch (vm_block_type(block)) {
1776 case block_type_iseq:
1777 case block_type_ifunc: return block->as.captured.ep;
1778 case block_type_proc: return vm_proc_ep(block->as.proc);
1779 case block_type_symbol: return NULL;
1780 }
1781 VM_UNREACHABLE(vm_block_ep);
1782 return NULL;
1783}
1784
1785static inline VALUE
1786vm_block_self(const struct rb_block *block)
1787{
1788 switch (vm_block_type(block)) {
1789 case block_type_iseq:
1790 case block_type_ifunc:
1791 return block->as.captured.self;
1792 case block_type_proc:
1793 return vm_block_self(vm_proc_block(block->as.proc));
1794 case block_type_symbol:
1795 return Qundef;
1796 }
1797 VM_UNREACHABLE(vm_block_self);
1798 return Qundef;
1799}
1800
1801static inline VALUE
1802VM_BH_TO_SYMBOL(VALUE block_handler)
1803{
1804 VM_ASSERT(SYMBOL_P(block_handler));
1805 return block_handler;
1806}
1807
1808static inline VALUE
1809VM_BH_FROM_SYMBOL(VALUE symbol)
1810{
1811 VM_ASSERT(SYMBOL_P(symbol));
1812 return symbol;
1813}
1814
1815static inline VALUE
1816VM_BH_TO_PROC(VALUE block_handler)
1817{
1818 VM_ASSERT(rb_obj_is_proc(block_handler));
1819 return block_handler;
1820}
1821
1822static inline VALUE
1823VM_BH_FROM_PROC(VALUE procval)
1824{
1825 VM_ASSERT(rb_obj_is_proc(procval));
1826 return procval;
1827}
1828
1829/* VM related object allocate functions */
1830VALUE rb_thread_alloc(VALUE klass);
1831VALUE rb_binding_alloc(VALUE klass);
1832VALUE rb_proc_alloc(VALUE klass);
1833VALUE rb_proc_dup(VALUE self);
1834
1835/* for debug */
1836extern bool rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
1837extern bool rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *);
1838extern bool rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
1839
1840#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr)
1841#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr)
1842bool rb_vm_bugreport(const void *, FILE *);
1843typedef void (*ruby_sighandler_t)(int);
1844RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
1845NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));
1846
1847/* functions about thread/vm execution */
1848RUBY_SYMBOL_EXPORT_BEGIN
1849VALUE rb_iseq_eval(const rb_iseq_t *iseq);
1850VALUE rb_iseq_eval_with_refinement(const rb_iseq_t *iseq, VALUE mod);
1851VALUE rb_iseq_eval_main(const rb_iseq_t *iseq);
1852VALUE rb_iseq_path(const rb_iseq_t *iseq);
1853VALUE rb_iseq_realpath(const rb_iseq_t *iseq);
1854RUBY_SYMBOL_EXPORT_END
1855
1856VALUE rb_iseq_pathobj_new(VALUE path, VALUE realpath);
1857void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath);
1858
1859int rb_ec_frame_method_id_and_class(const rb_execution_context_t *ec, ID *idp, ID *called_idp, VALUE *klassp);
1860void rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause);
1861
1862VALUE rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
1863
1864VALUE rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda);
1865static inline VALUE
1866rb_vm_make_proc(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass)
1867{
1868 return rb_vm_make_proc_lambda(ec, captured, klass, 0);
1869}
1870
1871static inline VALUE
1872rb_vm_make_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass)
1873{
1874 return rb_vm_make_proc_lambda(ec, captured, klass, 1);
1875}
1876
1877VALUE rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp);
1878VALUE rb_vm_env_local_variables(const rb_env_t *env);
1879VALUE rb_vm_env_numbered_parameters(const rb_env_t *env);
1880const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env);
1881const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars);
1882void rb_vm_inc_const_missing_count(void);
1883VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc,
1884 const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat);
1885void rb_vm_pop_frame_no_int(rb_execution_context_t *ec);
1886void rb_vm_pop_frame(rb_execution_context_t *ec);
1887
1888void rb_thread_start_timer_thread(void);
1889void rb_thread_stop_timer_thread(void);
1890void rb_thread_reset_timer_thread(void);
1891void rb_thread_wakeup_timer_thread(int);
1892
1893static inline void
1894rb_vm_living_threads_init(rb_vm_t *vm)
1895{
1896 ccan_list_head_init(&vm->workqueue);
1897 ccan_list_head_init(&vm->ractor.set);
1898#ifdef RUBY_THREAD_PTHREAD_H
1899 ccan_list_head_init(&vm->ractor.sched.zombie_threads);
1900#endif
1901}
1902
1903typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
1904rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1905rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1906VALUE *rb_vm_svar_lep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
1907int rb_vm_get_sourceline(const rb_control_frame_t *);
1908void rb_vm_stack_to_heap(rb_execution_context_t *ec);
1909void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame);
1910rb_thread_t * ruby_thread_from_native(void);
1911int ruby_thread_set_native(rb_thread_t *th);
1912int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp);
1913void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp);
1914void rb_vm_env_write(const VALUE *ep, int index, VALUE v);
1915VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler);
1916
1917void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE exception_class, VALUE mesg);
1918
1919#define rb_vm_register_special_exception(sp, e, m) \
1920 rb_vm_register_special_exception_str(sp, e, rb_usascii_str_new_static((m), (long)rb_strlen_lit(m)))
1921
1922void rb_gc_mark_machine_context(const rb_execution_context_t *ec);
1923
1924void rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_cref_t **new_cref_ptr);
1925
1926const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
1927
1928#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
1929
1930#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) do { \
1931 STATIC_ASSERT(sizeof_sp, sizeof(*(sp)) == sizeof(VALUE)); \
1932 STATIC_ASSERT(sizeof_cfp, sizeof(*(cfp)) == sizeof(rb_control_frame_t)); \
1933 const struct rb_control_frame_struct *bound = (void *)&(sp)[(margin)]; \
1934 if (UNLIKELY((cfp) <= &bound[1])) { \
1935 vm_stackoverflow(); \
1936 } \
1937} while (0)
1938
1939#define CHECK_VM_STACK_OVERFLOW(cfp, margin) \
1940 CHECK_VM_STACK_OVERFLOW0((cfp), (cfp)->sp, (margin))
1941
1942VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr);
1943
1944rb_execution_context_t *rb_vm_main_ractor_ec(rb_vm_t *vm); // ractor.c
1945
1946/* for thread */
1947
1948#if RUBY_VM_THREAD_MODEL == 2
1949
1950RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; // ractor.c
1951RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr;
1952RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags;
1953RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags;
1954RUBY_EXTERN unsigned int ruby_vm_event_local_num;
1955
1956#define GET_VM() rb_current_vm()
1957#define GET_RACTOR() rb_current_ractor()
1958#define GET_THREAD() rb_current_thread()
1959#define GET_EC() rb_current_execution_context(true)
1960
1961static inline rb_thread_t *
1962rb_ec_thread_ptr(const rb_execution_context_t *ec)
1963{
1964 return ec->thread_ptr;
1965}
1966
1967static inline rb_ractor_t *
1968rb_ec_ractor_ptr(const rb_execution_context_t *ec)
1969{
1970 const rb_thread_t *th = rb_ec_thread_ptr(ec);
1971 if (th) {
1972 VM_ASSERT(th->ractor != NULL);
1973 return th->ractor;
1974 }
1975 else {
1976 return NULL;
1977 }
1978}
1979
1980static inline rb_vm_t *
1981rb_ec_vm_ptr(const rb_execution_context_t *ec)
1982{
1983 const rb_thread_t *th = rb_ec_thread_ptr(ec);
1984 if (th) {
1985 return th->vm;
1986 }
1987 else {
1988 return NULL;
1989 }
1990}
1991
1992NOINLINE(struct rb_execution_context_struct *rb_current_ec_noinline(void));
1993
1994static inline rb_execution_context_t *
1995rb_current_execution_context(bool expect_ec)
1996{
1997#ifdef RB_THREAD_LOCAL_SPECIFIER
1998 #if defined(__arm64__) || defined(__aarch64__)
1999 rb_execution_context_t * volatile ec = rb_current_ec();
2000 #else
2001 rb_execution_context_t * volatile ec = ruby_current_ec;
2002 #endif
2003
2004 /* On the shared objects, `__tls_get_addr()` is used to access the TLS
2005 * and the address of the `ruby_current_ec` can be stored on a function
2006 * frame. However, this address can be mis-used after native thread
2007 * migration of a coroutine.
2008 * 1) Get `ptr =&ruby_current_ec` op NT1 and store it on the frame.
2009 * 2) Context switch and resume it on the NT2.
2010 * 3) `ptr` is used on NT2 but it accesses to the TLS on NT1.
2011 * This assertion checks such misusage.
2012 *
2013 * To avoid accidents, `GET_EC()` should be called once on the frame.
2014 * Note that inlining can produce the problem.
2015 */
2016 VM_ASSERT(ec == rb_current_ec_noinline());
2017#else
2018 rb_execution_context_t * volatile ec = native_tls_get(ruby_current_ec_key);
2019#endif
2020 VM_ASSERT(!expect_ec || ec != NULL);
2021 return ec;
2022}
2023
2024static inline rb_thread_t *
2025rb_current_thread(void)
2026{
2027 const rb_execution_context_t *ec = GET_EC();
2028 return rb_ec_thread_ptr(ec);
2029}
2030
2031static inline rb_ractor_t *
2032rb_current_ractor_raw(bool expect)
2033{
2034 if (ruby_single_main_ractor) {
2035 return ruby_single_main_ractor;
2036 }
2037 else {
2038 const rb_execution_context_t *ec = rb_current_execution_context(expect);
2039 return (expect || ec) ? rb_ec_ractor_ptr(ec) : NULL;
2040 }
2041}
2042
2043static inline rb_ractor_t *
2044rb_current_ractor(void)
2045{
2046 return rb_current_ractor_raw(true);
2047}
2048
2049static inline rb_vm_t *
2050rb_current_vm(void)
2051{
2052#if 0 // TODO: reconsider the assertions
2053 VM_ASSERT(ruby_current_vm_ptr == NULL ||
2054 ruby_current_execution_context_ptr == NULL ||
2055 rb_ec_thread_ptr(GET_EC()) == NULL ||
2056 rb_ec_thread_ptr(GET_EC())->status == THREAD_KILLED ||
2057 rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr);
2058#endif
2059
2060 return ruby_current_vm_ptr;
2061}
2062
2063void rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec,
2064 unsigned int recorded_lock_rec,
2065 unsigned int current_lock_rec);
2066
2067static inline unsigned int
2068rb_ec_vm_lock_rec(const rb_execution_context_t *ec)
2069{
2070 rb_vm_t *vm = rb_ec_vm_ptr(ec);
2071
2072 if (vm->ractor.sync.lock_owner != rb_ec_ractor_ptr(ec)) {
2073 return 0;
2074 }
2075 else {
2076 return vm->ractor.sync.lock_rec;
2077 }
2078}
2079
2080#else
2081#error "unsupported thread model"
2082#endif
2083
2084enum {
2085 TIMER_INTERRUPT_MASK = 0x01,
2086 PENDING_INTERRUPT_MASK = 0x02,
2087 POSTPONED_JOB_INTERRUPT_MASK = 0x04,
2088 TRAP_INTERRUPT_MASK = 0x08,
2089 TERMINATE_INTERRUPT_MASK = 0x10,
2090 VM_BARRIER_INTERRUPT_MASK = 0x20,
2091};
2092
2093#define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK)
2094#define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK)
2095#define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK)
2096#define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK)
2097#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK)
2098#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK)
2099
2100static inline bool
2101RUBY_VM_INTERRUPTED(rb_execution_context_t *ec)
2102{
2103 return (ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec->interrupt_mask) & (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK));
2104}
2105
2106static inline bool
2107RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec)
2108{
2109#if defined(USE_VM_CLOCK) && USE_VM_CLOCK
2110 uint32_t current_clock = rb_ec_vm_ptr(ec)->clock;
2111
2112 if (current_clock != ec->checked_clock) {
2113 ec->checked_clock = current_clock;
2114 RUBY_VM_SET_TIMER_INTERRUPT(ec);
2115 }
2116#endif
2117 return ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec)->interrupt_mask;
2118}
2119
2120VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
2121int rb_signal_buff_size(void);
2122int rb_signal_exec(rb_thread_t *th, int sig);
2123void rb_threadptr_check_signal(rb_thread_t *mth);
2124void rb_threadptr_signal_raise(rb_thread_t *th, int sig);
2125void rb_threadptr_signal_exit(rb_thread_t *th);
2126int rb_threadptr_execute_interrupts(rb_thread_t *, int);
2127void rb_threadptr_interrupt(rb_thread_t *th);
2128void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th);
2129void rb_threadptr_pending_interrupt_clear(rb_thread_t *th);
2130void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v);
2131VALUE rb_ec_get_errinfo(const rb_execution_context_t *ec);
2132void rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo);
2133void rb_execution_context_update(rb_execution_context_t *ec);
2134void rb_execution_context_mark(const rb_execution_context_t *ec);
2135void rb_fiber_close(rb_fiber_t *fib);
2136void Init_native_thread(rb_thread_t *th);
2137int rb_vm_check_ints_blocking(rb_execution_context_t *ec);
2138
2139// vm_sync.h
2140void rb_vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond);
2141void rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec);
2142
2143#define RUBY_VM_CHECK_INTS(ec) rb_vm_check_ints(ec)
2144static inline void
2145rb_vm_check_ints(rb_execution_context_t *ec)
2146{
2147#ifdef RUBY_ASSERT_CRITICAL_SECTION
2148 VM_ASSERT(ruby_assert_critical_section_entered == 0);
2149#endif
2150
2151 VM_ASSERT(ec == rb_current_ec_noinline());
2152
2153 if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {
2154 rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);
2155 }
2156}
2157
2158/* tracer */
2159
2161 rb_event_flag_t event;
2163 const rb_control_frame_t *cfp;
2164 VALUE self;
2165 ID id;
2166 ID called_id;
2167 VALUE klass;
2168 VALUE data;
2169
2170 int klass_solved;
2171
2172 /* calc from cfp */
2173 int lineno;
2174 VALUE path;
2175};
2176
2177void rb_hook_list_mark(rb_hook_list_t *hooks);
2178void rb_hook_list_mark_and_update(rb_hook_list_t *hooks);
2179void rb_hook_list_free(rb_hook_list_t *hooks);
2180void rb_hook_list_connect_tracepoint(VALUE target, rb_hook_list_t *list, VALUE tpval, unsigned int target_line);
2181void rb_hook_list_remove_tracepoint(rb_hook_list_t *list, VALUE tpval);
2182
2183void rb_exec_event_hooks(struct rb_trace_arg_struct *trace_arg, rb_hook_list_t *hooks, int pop_p);
2184
2185#define EXEC_EVENT_HOOK_ORIG(ec_, hooks_, flag_, self_, id_, called_id_, klass_, data_, pop_p_) do { \
2186 const rb_event_flag_t flag_arg_ = (flag_); \
2187 rb_hook_list_t *hooks_arg_ = (hooks_); \
2188 if (UNLIKELY((hooks_arg_)->events & (flag_arg_))) { \
2189 /* defer evaluating the other arguments */ \
2190 rb_exec_event_hook_orig(ec_, hooks_arg_, flag_arg_, self_, id_, called_id_, klass_, data_, pop_p_); \
2191 } \
2192} while (0)
2193
2194static inline void
2195rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_event_flag_t flag,
2196 VALUE self, ID id, ID called_id, VALUE klass, VALUE data, int pop_p)
2197{
2198 struct rb_trace_arg_struct trace_arg;
2199
2200 VM_ASSERT((hooks->events & flag) != 0);
2201
2202 trace_arg.event = flag;
2203 trace_arg.ec = ec;
2204 trace_arg.cfp = ec->cfp;
2205 trace_arg.self = self;
2206 trace_arg.id = id;
2207 trace_arg.called_id = called_id;
2208 trace_arg.klass = klass;
2209 trace_arg.data = data;
2210 trace_arg.path = Qundef;
2211 trace_arg.klass_solved = 0;
2212
2213 rb_exec_event_hooks(&trace_arg, hooks, pop_p);
2214}
2215
2217 VALUE self;
2218 uint32_t id;
2219 rb_hook_list_t hooks;
2220};
2221
2222static inline rb_hook_list_t *
2223rb_ec_ractor_hooks(const rb_execution_context_t *ec)
2224{
2225 struct rb_ractor_pub *cr_pub = (struct rb_ractor_pub *)rb_ec_ractor_ptr(ec);
2226 return &cr_pub->hooks;
2227}
2228
2229#define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \
2230 EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0)
2231
2232#define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \
2233 EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1)
2234
2235static inline void
2236rb_exec_event_hook_script_compiled(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE eval_script)
2237{
2238 EXEC_EVENT_HOOK(ec, RUBY_EVENT_SCRIPT_COMPILED, ec->cfp->self, 0, 0, 0,
2239 NIL_P(eval_script) ? (VALUE)iseq :
2240 rb_ary_new_from_args(2, eval_script, (VALUE)iseq));
2241}
2242
2243void rb_vm_trap_exit(rb_vm_t *vm);
2244void rb_vm_postponed_job_atfork(void); /* vm_trace.c */
2245void rb_vm_postponed_job_free(void); /* vm_trace.c */
2246size_t rb_vm_memsize_postponed_job_queue(void); /* vm_trace.c */
2247void rb_vm_postponed_job_queue_init(rb_vm_t *vm); /* vm_trace.c */
2248
2249RUBY_SYMBOL_EXPORT_BEGIN
2250
2251int rb_thread_check_trap_pending(void);
2252
2253/* #define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 */ /* from vm_core.h */
2254#define RUBY_EVENT_COVERAGE_LINE 0x010000
2255#define RUBY_EVENT_COVERAGE_BRANCH 0x020000
2256
2257extern VALUE rb_get_coverages(void);
2258extern void rb_set_coverages(VALUE, int, VALUE);
2259extern void rb_clear_coverages(void);
2260extern void rb_reset_coverages(void);
2261extern void rb_resume_coverages(void);
2262extern void rb_suspend_coverages(void);
2263
2264void rb_postponed_job_flush(rb_vm_t *vm);
2265
2266// ractor.c
2267RUBY_EXTERN VALUE rb_eRactorUnsafeError;
2268RUBY_EXTERN VALUE rb_eRactorIsolationError;
2269
2270RUBY_SYMBOL_EXPORT_END
2271
2272#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
uint32_t rb_event_flag_t
Represents event(s).
Definition event.h:108
#define RBIMPL_ATTR_FORMAT(x, y, z)
Wraps (or simulates) __attribute__((format))
Definition format.h:29
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#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:1397
VALUE rb_obj_is_proc(VALUE recv)
Queries if the given object is a proc.
Definition proc.c:120
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.
#define RBIMPL_ATTR_NONNULL(list)
Wraps (or simulates) __attribute__((nonnull))
Definition nonnull.h:30
#define inline
Old Visual Studio versions do not support the inline keyword, so we need to define it to be __inline.
Definition defines.h:91
Functions related to nodes in the AST.
#define RARRAY_AREF(a, i)
Definition rarray.h:403
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition rtypeddata.h:102
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
Defines old _.
C99 shim for <stdbool.h>
Definition vm_core.h:261
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
Definition vm_core.h:287
Definition vm_core.h:295
Definition vm_core.h:290
Definition iseq.h:251
Definition method.h:63
CREF (Class REFerence)
Definition method.h:45
Definition class.h:72
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:203
struct rb_iseq_constant_body::@153 param
parameter information
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
Definition method.h:136
Internal header for Namespace.
Definition namespace.h:14
Definition st.h:79
IFUNC (Internal FUNCtion)
Definition imemo.h:86
Definition vm_core.h:253
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