Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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
15 static void vm_analysis_insn(int insn);
16 #endif
17
18 #if VMDEBUG > 0
19 #define DECL_SC_REG(type, r, reg) register type reg_##r
20
21 #elif defined(__GNUC__) && defined(__x86_64__)
22 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
23
24 #elif defined(__GNUC__) && defined(__i386__)
25 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
26
27 #elif defined(__GNUC__) && defined(__powerpc64__)
28 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
29
30 #else
31 #define DECL_SC_REG(type, r, reg) register type reg_##r
32 #endif
33 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
34
35 #if VM_DEBUG_STACKOVERFLOW
36 NORETURN(static void vm_stack_overflow_for_insn(void));
37 static void
38 vm_stack_overflow_for_insn(void)
39 {
40 rb_bug("CHECK_VM_STACK_OVERFLOW_FOR_INSN: should not overflow here. "
41 "Please contact ruby-core/dev with your (a part of) script. "
42 "This check will be removed soon.");
43 }
44 #endif
45
46 #if !OPT_CALL_THREADED_CODE
47 static VALUE
48 vm_exec_core(rb_execution_context_t *ec, VALUE initial)
49 {
50
51 #if OPT_STACK_CACHING
52 #if 0
53 #elif __GNUC__ && __x86_64__
54 DECL_SC_REG(VALUE, a, "12");
55 DECL_SC_REG(VALUE, b, "13");
56 #else
57 register VALUE reg_a;
58 register VALUE reg_b;
59 #endif
60 #endif
61
62 #if defined(__GNUC__) && defined(__i386__)
63 DECL_SC_REG(const VALUE *, pc, "di");
64 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
65 #define USE_MACHINE_REGS 1
66
67 #elif defined(__GNUC__) && defined(__x86_64__)
68 DECL_SC_REG(const VALUE *, pc, "14");
69 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
70 #define USE_MACHINE_REGS 1
71
72 #elif defined(__GNUC__) && defined(__powerpc64__)
73 DECL_SC_REG(const VALUE *, pc, "14");
74 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
75 #define USE_MACHINE_REGS 1
76
77 #else
78 register rb_control_frame_t *reg_cfp;
79 const VALUE *reg_pc;
80 #endif
81
82 #if USE_MACHINE_REGS
83
84 #undef RESTORE_REGS
85 #define RESTORE_REGS() \
86 { \
87 VM_REG_CFP = ec->cfp; \
88 reg_pc = reg_cfp->pc; \
89 }
90
91 #undef VM_REG_PC
92 #define VM_REG_PC reg_pc
93 #undef GET_PC
94 #define GET_PC() (reg_pc)
95 #undef SET_PC
96 #define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
97 #endif
98
99 #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
100 #include "vmtc.inc"
101 if (UNLIKELY(ec == 0)) {
102 return (VALUE)insns_address_table;
103 }
104 #endif
105 reg_cfp = ec->cfp;
106 reg_pc = reg_cfp->pc;
107
108 #if OPT_STACK_CACHING
109 reg_a = initial;
110 reg_b = 0;
111 #endif
112
113 first:
114 INSN_DISPATCH();
115 /*****************/
116 #include "vm.inc"
117 /*****************/
118 END_INSNS_DISPATCH();
119
120 /* unreachable */
121 rb_bug("vm_eval: unreachable");
122 goto first;
123 }
124
125 const void **
126 rb_vm_get_insns_address_table(void)
127 {
128 return (const void **)vm_exec_core(0, 0);
129 }
130
131 #else /* OPT_CALL_THREADED_CODE */
132
133 #include "vm.inc"
134 #include "vmtc.inc"
135
136 const void **
137 rb_vm_get_insns_address_table(void)
138 {
139 return (const void **)insns_address_table;
140 }
141
142 static VALUE
143 vm_exec_core(rb_execution_context_t *ec, VALUE initial)
144 {
145 register rb_control_frame_t *reg_cfp = ec->cfp;
146 rb_thread_t *th;
147
148 while (1) {
149 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
150
151 if (UNLIKELY(reg_cfp == 0)) {
152 break;
153 }
154 }
155
156 if ((th = rb_ec_thread_ptr(ec))->retval != Qundef) {
157 VALUE ret = th->retval;
158 th->retval = Qundef;
159 return ret;
160 }
161 else {
162 VALUE err = ec->errinfo;
163 ec->errinfo = Qnil;
164 return err;
165 }
166 }
167 #endif
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
reg_cfp
rb_control_frame_t * reg_cfp
Definition: rb_mjit_min_header-2.7.0.h:15146
GET_PC
#define GET_PC()
Definition: vm_insnhelper.h:79
NORETURN
#define NORETURN(x)
Definition: defines.h:528
VALUE
unsigned long VALUE
Definition: ruby.h:102
Qundef
#define Qundef
Definition: ruby.h:470
END_INSNS_DISPATCH
#define END_INSNS_DISPATCH()
Definition: vm_exec.h:147
INSN_DISPATCH
#define INSN_DISPATCH()
Definition: vm_exec.h:143
pc
rb_control_frame_t const VALUE * pc
Definition: rb_mjit_min_header-2.7.0.h:16923
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
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:1143
rb_execution_context_struct::errinfo
VALUE errinfo
Definition: vm_core.h:875
rb_control_frame_struct
Definition: vm_core.h:760
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
rb_vm_get_insns_address_table
const void ** rb_vm_get_insns_address_table(void)
Definition: vm_exec.c:126
DECL_SC_REG
#define DECL_SC_REG(type, r, reg)
Definition: vm_exec.c:31
err
int err
Definition: win32.c:135
rb_control_frame_struct::pc
const VALUE * pc
Definition: vm_core.h:761
Qnil
#define Qnil
Definition: ruby.h:469
rb_thread_struct
Definition: vm_core.h:910
cfp
rb_control_frame_t * cfp
Definition: rb_mjit_min_header-2.7.0.h:14544
rb_execution_context_struct
Definition: vm_core.h:843