Ruby: vm_exec.c Source File

Ruby 3.4.6p54 (2025-09-16 revision dbd83256b1cec76c69756ecb8758b9e1079833de)

vm_exec.c
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_RJIT
15// The number of instructions executed on vm_exec_core. --yjit-stats uses this.
16uint64_t rb_vm_insns_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#define USE_MACHINE_REGS 1
51
52#elif defined(__GNUC__) && defined(__x86_64__)
53 DECL_SC_REG(const VALUE *, pc, "14");
54 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
55#define USE_MACHINE_REGS 1
56
57#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
58 DECL_SC_REG(const VALUE *, pc, "14");
59 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
60#define USE_MACHINE_REGS 1
61
62#elif defined(__GNUC__) && defined(__aarch64__)
63 DECL_SC_REG(const VALUE *, pc, "19");
64 DECL_SC_REG(rb_control_frame_t *, cfp, "20");
65#define USE_MACHINE_REGS 1
66
67#else
68 register rb_control_frame_t *reg_cfp;
69 const VALUE *reg_pc;
70#define USE_MACHINE_REGS 0
71
72#endif
73
74#if USE_MACHINE_REGS
75
76#undef RESTORE_REGS
77#define RESTORE_REGS() \
78{ \
79 VM_REG_CFP = ec->cfp; \
80 reg_pc = reg_cfp->pc; \
81}
82
83#undef VM_REG_PC
84#define VM_REG_PC reg_pc
85#undef GET_PC
86#define GET_PC() (reg_pc)
87#undef SET_PC
88#define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
89#endif
90
91#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
92#include "vmtc.inc"
93 if (UNLIKELY(ec == 0)) {
94 return (VALUE)insns_address_table;
95 }
96#endif
97 reg_cfp = ec->cfp;
98 reg_pc = reg_cfp->pc;
99
100 first:
101 INSN_DISPATCH();
102/*****************/
103 #include "vm.inc"
104/*****************/
105 END_INSNS_DISPATCH();
106
107 /* unreachable */
108 rb_bug("vm_eval: unreachable");
109 goto first;
110}
111
112const void **
113rb_vm_get_insns_address_table(void)
114{
115 return (const void **)vm_exec_core(0);
116}
117
118#else /* OPT_CALL_THREADED_CODE */
119
120#include "vm.inc"
121#include "vmtc.inc"
122
123const void **
124rb_vm_get_insns_address_table(void)
125{
126 return (const void **)insns_address_table;
127}
128
129static VALUE
130vm_exec_core(rb_execution_context_t *ec)
131{
132 register rb_control_frame_t *reg_cfp = ec->cfp;
133 rb_thread_t *th;
134
135 while (1) {
136 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
137
138 if (UNLIKELY(reg_cfp == 0)) {
139 break;
140 }
141 }
142
143 if (!UNDEF_P((th = rb_ec_thread_ptr(ec))->retval)) {
144 VALUE ret = th->retval;
145 th->retval = Qundef;
146 return ret;
147 }
148 else {
149 VALUE err = ec->errinfo;
150 ec->errinfo = Qnil;
151 return err;
152 }
153}
154#endif
Qundef
#define Qundef
Old name of RUBY_Qundef.
Definition special_consts.h:62
Qnil
#define Qnil
Old name of RUBY_Qnil.
Definition special_consts.h:60
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40