Ruby 4.1.0dev (2026-10-06 revision 6b1add1e701dcde4be05d63f3f423ef37c3893a4)
vm_exec.c (6b1add1e701dcde4be05d63f3f423ef37c3893a4)
1/* -*-c-*- */
2/**********************************************************************
3
4 vm_exec.c -
5
6 $Author$
7
8 Copyright (C) 2004-2007 Koichi Sasada
9
10**********************************************************************/
11
12#include <math.h>
13
14#if USE_YJIT || USE_ZJIT
15// The number of instructions executed on vm_exec_core. --yjit-stats and --zjit-stats use this.
16uint64_t rb_vm_insn_count = 0;
17#endif
18
19#if VM_COLLECT_USAGE_DETAILS
20static void vm_analysis_insn(int insn);
21#endif
22
23#if VMDEBUG > 0
24#define DECL_SC_REG(type, r, reg) register type reg_##r
25
26#elif defined(__GNUC__) && defined(__x86_64__)
27#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
28
29#elif defined(__GNUC__) && defined(__i386__)
30#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
31
32#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
33#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
34
35#elif defined(__GNUC__) && defined(__aarch64__)
36#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
37
38#else
39#define DECL_SC_REG(type, r, reg) register type reg_##r
40#endif
41/* #define DECL_SC_REG(r, reg) VALUE reg_##r */
42
43#if !OPT_CALL_THREADED_CODE
44static VALUE
45vm_exec_core(rb_execution_context_t *ec)
46{
47#if defined(__GNUC__) && defined(__i386__)
48 DECL_SC_REG(const VALUE *, pc, "di");
49 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
50
51#elif defined(__GNUC__) && defined(__x86_64__)
52 DECL_SC_REG(const VALUE *, pc, "14");
53 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
54
55#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
56 DECL_SC_REG(const VALUE *, pc, "14");
57 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
58
59#elif defined(__GNUC__) && defined(__aarch64__)
60 DECL_SC_REG(const VALUE *, pc, "19");
61 DECL_SC_REG(rb_control_frame_t *, cfp, "20");
62
63#else
64 register rb_control_frame_t *reg_cfp;
65 const VALUE *reg_pc;
66
67#endif
68
69#undef RESTORE_REGS
70#define RESTORE_REGS() \
71{ \
72 VM_REG_CFP = ec->cfp; \
73 reg_pc = reg_cfp->pc; \
74}
75
76#undef VM_REG_PC
77#define VM_REG_PC reg_pc
78#undef GET_PC
79#define GET_PC() (reg_pc)
80#undef SET_PC
81#define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
82
83#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
84#include "vmtc.inc"
85 if (UNLIKELY(ec == 0)) {
86 return (VALUE)insns_address_table;
87 }
88#endif
89 reg_cfp = ec->cfp;
90 reg_pc = reg_cfp->pc;
91
92 first:
93 INSN_DISPATCH();
94/*****************/
95 #include "vm.inc"
96/*****************/
97 END_INSNS_DISPATCH();
98
99 /* unreachable */
100 rb_bug("vm_eval: unreachable");
101 goto first;
102}
103
104const void **
105rb_vm_get_insns_address_table(void)
106{
107 return (const void **)vm_exec_core(0);
108}
109
110#else /* OPT_CALL_THREADED_CODE */
111
112#include "vm.inc"
113#include "vmtc.inc"
114
115const void **
116rb_vm_get_insns_address_table(void)
117{
118 return (const void **)insns_address_table;
119}
120
121static VALUE
122vm_exec_core(rb_execution_context_t *ec)
123{
124 register rb_control_frame_t *reg_cfp = ec->cfp;
125 rb_thread_t *th;
126
127 while (1) {
128 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
129
130 if (UNLIKELY(reg_cfp == 0)) {
131 break;
132 }
133 }
134
135 if (!UNDEF_P((th = rb_ec_thread_ptr(ec))->retval)) {
136 VALUE ret = th->retval;
137 th->retval = Qundef;
138 return ret;
139 }
140 else {
141 VALUE err = ec->errinfo;
142 ec->errinfo = Qnil;
143 return err;
144 }
145}
146#endif
#define Qundef
Old name of RUBY_Qundef.
#define Qnil
Old name of RUBY_Qnil.
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40