Ruby: vm_exec.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

vm_exec.c
Go to the documentation of this file.
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 VM_COLLECT_USAGE_DETAILS
15static void vm_analysis_insn(int insn);
16#endif
17
18#if USE_INSNS_COUNTER
19static size_t rb_insns_counter[VM_INSTRUCTION_SIZE];
20
21static void
22vm_insns_counter_count_insn(int insn)
23{
24 rb_insns_counter[insn]++;
25}
26
27 __attribute__((destructor))
28static void
29vm_insns_counter_show_results_at_exit(void)
30{
31 int insn_end = (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS)
32 ? VM_INSTRUCTION_SIZE : VM_INSTRUCTION_SIZE / 2;
33
34 size_t total = 0;
35 for (int insn = 0; insn < insn_end; insn++)
36 total += rb_insns_counter[insn];
37
38 for (int insn = 0; insn < insn_end; insn++) {
39 fprintf(stderr, "[RUBY_INSNS_COUNTER]\t%-32s%'12"PRIuSIZE" (%4.1f%%)\n",
40 insn_name(insn), rb_insns_counter[insn],
41 100.0 * rb_insns_counter[insn] / total);
42 }
43}
44#else
45static void vm_insns_counter_count_insn(int insn) {}
46#endif
47
48#if VMDEBUG > 0
49#define DECL_SC_REG(type, r, reg) register type reg_##r
50
51#elif defined(__GNUC__) && defined(__x86_64__)
52#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
53
54#elif defined(__GNUC__) && defined(__i386__)
55#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
56
57#elif defined(__GNUC__) && defined(__powerpc64__)
58#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
59
60#elif defined(__GNUC__) && defined(__aarch64__)
61#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
62
63#else
64#define DECL_SC_REG(type, r, reg) register type reg_##r
65#endif
66/* #define DECL_SC_REG(r, reg) VALUE reg_##r */
67
68#if !OPT_CALL_THREADED_CODE
69static VALUE
70vm_exec_core(rb_execution_context_t *ec, VALUE initial)
71{
72
73#if OPT_STACK_CACHING
74#if 0
75#elif __GNUC__ && __x86_64__
76 DECL_SC_REG(VALUE, a, "12");
77 DECL_SC_REG(VALUE, b, "13");
78#else
79 register VALUE reg_a;
80 register VALUE reg_b;
81#endif
82#endif
83
84#if defined(__GNUC__) && defined(__i386__)
85 DECL_SC_REG(const VALUE *, pc, "di");
86 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
87#define USE_MACHINE_REGS 1
88
89#elif defined(__GNUC__) && defined(__x86_64__)
90 DECL_SC_REG(const VALUE *, pc, "14");
91 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
92#define USE_MACHINE_REGS 1
93
94#elif defined(__GNUC__) && defined(__powerpc64__)
95 DECL_SC_REG(const VALUE *, pc, "14");
96 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
97#define USE_MACHINE_REGS 1
98
99#elif defined(__GNUC__) && defined(__aarch64__)
100 DECL_SC_REG(const VALUE *, pc, "19");
101 DECL_SC_REG(rb_control_frame_t *, cfp, "20");
102#define USE_MACHINE_REGS 1
103
104#else
105 register rb_control_frame_t *reg_cfp;
106 const VALUE *reg_pc;
107#endif
108
109#if USE_MACHINE_REGS
110
111#undef RESTORE_REGS
112#define RESTORE_REGS() \
113{ \
114 VM_REG_CFP = ec->cfp; \
115 reg_pc = reg_cfp->pc; \
116}
117
118#undef VM_REG_PC
119#define VM_REG_PC reg_pc
120#undef GET_PC
121#define GET_PC() (reg_pc)
122#undef SET_PC
123#define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
124#endif
125
126#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
127#include "vmtc.inc"
128 if (UNLIKELY(ec == 0)) {
129 return (VALUE)insns_address_table;
130 }
131#endif
132 reg_cfp = ec->cfp;
133 reg_pc = reg_cfp->pc;
134
135#if OPT_STACK_CACHING
136 reg_a = initial;
137 reg_b = 0;
138#endif
139
140 first:
141 INSN_DISPATCH();
142/*****************/
143 #include "vm.inc"
144/*****************/
145 END_INSNS_DISPATCH();
146
147 /* unreachable */
148 rb_bug("vm_eval: unreachable");
149 goto first;
150}
151
152const void **
153 rb_vm_get_insns_address_table(void)
154{
155 return (const void **)vm_exec_core(0, 0);
156}
157
158#else /* OPT_CALL_THREADED_CODE */
159
160#include "vm.inc"
161#include "vmtc.inc"
162
163const void **
164 rb_vm_get_insns_address_table(void)
165{
166 return (const void **)insns_address_table;
167}
168
169static VALUE
170vm_exec_core(rb_execution_context_t *ec, VALUE initial)
171{
172 register rb_control_frame_t *reg_cfp = ec->cfp;
173 rb_thread_t *th;
174
175 while (1) {
176 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
177
178 if (UNLIKELY(reg_cfp == 0)) {
179 break;
180 }
181 }
182
183 if ((th = rb_ec_thread_ptr(ec))->retval != Qundef) {
184 VALUE ret = th->retval;
185 th->retval = Qundef;
186 return ret;
187 }
188 else {
189 VALUE err = ec->errinfo;
190 ec->errinfo = Qnil;
191 return err;
192 }
193}
194#endif
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:768
__attribute__
void *PTR64 __attribute__((mode(DI)))
Definition: ffi.c:41
PRIuSIZE
#define PRIuSIZE
Definition: inttypes.h:127
ISEQ_TRACE_EVENTS
#define ISEQ_TRACE_EVENTS
Definition: iseq.h:68
math.h
Internal header for Math.
Qundef
#define Qundef
Definition: special_consts.h:53
Qnil
#define Qnil
Definition: special_consts.h:51
rb_control_frame_struct
Definition: vm_core.h:769
rb_control_frame_struct::pc
const VALUE * pc
Definition: vm_core.h:770
rb_execution_context_struct
Definition: vm_core.h:854
rb_execution_context_struct::errinfo
VALUE errinfo
Definition: vm_core.h:889
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:858
rb_thread_struct
Definition: vm_core.h:935
VALUE
unsigned long VALUE
Definition: value.h:38
ruby_vm_event_enabled_global_flags
rb_event_flag_t ruby_vm_event_enabled_global_flags
Definition: vm.c:404
rb_insn_func_t
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_execution_context_t *, rb_control_frame_t *)
Definition: vm_core.h:1158
rb_vm_get_insns_address_table
const void ** rb_vm_get_insns_address_table(void)
Definition: vm_exec.c:153
DECL_SC_REG
#define DECL_SC_REG(type, r, reg)
Definition: vm_exec.c:64
INSN_DISPATCH
#define INSN_DISPATCH()
Definition: vm_exec.h:147
END_INSNS_DISPATCH
#define END_INSNS_DISPATCH()
Definition: vm_exec.h:151
GET_PC
#define GET_PC()
Definition: vm_insnhelper.h:77
err
int err
Definition: win32.c:142