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