Ruby 3.2.1p31 (2023-02-08 revision 31819e82c88c6f8ecfaeb162519bfa26a14b21fd)
vm_exec.h
1#ifndef RUBY_VM_EXEC_H
2#define RUBY_VM_EXEC_H
3/**********************************************************************
4
5 vm.h -
6
7 $Author$
8 created at: 04/01/01 16:56:59 JST
9
10 Copyright (C) 2004-2007 Koichi Sasada
11
12**********************************************************************/
13
14typedef long OFFSET;
15typedef unsigned long lindex_t;
16typedef VALUE GENTRY;
17typedef rb_iseq_t *ISEQ;
18
19#if VMDEBUG > 0
20#define debugs printf
21#define DEBUG_ENTER_INSN(insn) \
22 rb_vmdebug_debug_print_pre(ec, GET_CFP(), GET_PC());
23
24#if OPT_STACK_CACHING
25#define SC_REGS() , reg_a, reg_b
26#else
27#define SC_REGS()
28#endif
29
30#define DEBUG_END_INSN() \
31 rb_vmdebug_debug_print_post(ec, GET_CFP() SC_REGS());
32
33#else
34
35#define debugs
36#define DEBUG_ENTER_INSN(insn)
37#define DEBUG_END_INSN()
38#endif
39
40#define throwdebug if(0)ruby_debug_printf
41/* #define throwdebug ruby_debug_printf */
42
43#ifndef USE_INSNS_COUNTER
44#define USE_INSNS_COUNTER 0
45#endif
46
47/************************************************/
48#if defined(DISPATCH_XXX)
49error !
50/************************************************/
51#elif OPT_CALL_THREADED_CODE
52
53#define LABEL(x) insn_func_##x
54#define ELABEL(x)
55#define LABEL_PTR(x) &LABEL(x)
56
57#define INSN_ENTRY(insn) \
58 static rb_control_frame_t * \
59 FUNC_FASTCALL(LABEL(insn))(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) {
60
61#define END_INSN(insn) return reg_cfp;}
62
63#define NEXT_INSN() return reg_cfp;
64
65#define START_OF_ORIGINAL_INSN(x) /* ignore */
66#define DISPATCH_ORIGINAL_INSN(x) return LABEL(x)(ec, reg_cfp);
67
68/************************************************/
69#elif OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
70/* threaded code with gcc */
71
72#define LABEL(x) INSN_LABEL_##x
73#define ELABEL(x) INSN_ELABEL_##x
74#define LABEL_PTR(x) RB_GNUC_EXTENSION(&&LABEL(x))
75
76#define INSN_ENTRY_SIG(insn) \
77 if (0) { \
78 ruby_debug_printf("exec: %s@(%"PRIdPTRDIFF", %"PRIdPTRDIFF")@%s:%u\n", #insn, \
79 (reg_pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded), \
80 (reg_cfp->pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded), \
81 RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \
82 rb_iseq_line_no(reg_cfp->iseq, reg_pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded)); \
83 } \
84 if (USE_INSNS_COUNTER) vm_insns_counter_count_insn(BIN(insn));
85
86#define INSN_DISPATCH_SIG(insn)
87
88#define INSN_ENTRY(insn) \
89 LABEL(insn): \
90 INSN_ENTRY_SIG(insn); \
91
92/**********************************/
93#if OPT_DIRECT_THREADED_CODE
94
95/* for GCC 3.4.x */
96#define TC_DISPATCH(insn) \
97 INSN_DISPATCH_SIG(insn); \
98 RB_GNUC_EXTENSION_BLOCK(goto *(void const *)GET_CURRENT_INSN()); \
99 ;
100
101#else
102/* token threaded code */
103
104/* dispatcher */
105#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && __GNUC__ == 3
106#define DISPATCH_ARCH_DEPEND_WAY(addr) \
107 __asm__ __volatile__("jmp *%0;\t# -- inserted by vm.h\t[length = 2]" : : "r" (addr))
108
109#else
110#define DISPATCH_ARCH_DEPEND_WAY(addr) \
111 /* do nothing */
112#endif
113#define TC_DISPATCH(insn) \
114 DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
115 INSN_DISPATCH_SIG(insn); \
116 RB_GNUC_EXTENSION_BLOCK(goto *insns_address_table[GET_CURRENT_INSN()]); \
117 rb_bug("tc error");
118
119#endif /* OPT_DIRECT_THREADED_CODE */
120
121#define END_INSN(insn) \
122 DEBUG_END_INSN(); \
123 TC_DISPATCH(insn);
124
125#define INSN_DISPATCH() \
126 TC_DISPATCH(__START__) \
127 {
128
129#define END_INSNS_DISPATCH() \
130 rb_bug("unknown insn: %"PRIdVALUE, GET_CURRENT_INSN()); \
131 } /* end of while loop */ \
132
133#define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
134
135/************************************************/
136#else /* no threaded code */
137/* most common method */
138
139#define INSN_ENTRY(insn) \
140case BIN(insn):
141
142#define END_INSN(insn) \
143 DEBUG_END_INSN(); \
144 break;
145
146#define INSN_DISPATCH() \
147 while (1) { \
148 switch (GET_CURRENT_INSN()) {
149
150#define END_INSNS_DISPATCH() \
151default: \
152 SDR(); \
153 rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
154 } /* end of switch */ \
155 } /* end of while loop */ \
156
157#define NEXT_INSN() goto first
158
159#endif
160
161#ifndef START_OF_ORIGINAL_INSN
162#define START_OF_ORIGINAL_INSN(x) if (0) goto start_of_##x; start_of_##x:
163#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
164#endif
165
166#define VM_SP_CNT(ec, sp) ((sp) - (ec)->vm_stack)
167
168#ifdef MJIT_HEADER
169#define THROW_EXCEPTION(exc) do { \
170 ec->errinfo = (VALUE)(exc); \
171 EC_JUMP_TAG(ec, ec->tag->state); \
172} while (0)
173#else
174#if OPT_CALL_THREADED_CODE
175#define THROW_EXCEPTION(exc) do { \
176 ec->errinfo = (VALUE)(exc); \
177 return 0; \
178} while (0)
179#else
180#define THROW_EXCEPTION(exc) return (VALUE)(exc)
181#endif
182#endif
183
184#define SCREG(r) (reg_##r)
185
186#define VM_DEBUG_STACKOVERFLOW 0
187
188#if VM_DEBUG_STACKOVERFLOW
189#define CHECK_VM_STACK_OVERFLOW_FOR_INSN CHECK_VM_STACK_OVERFLOW
190#else
191#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
192#endif
193
194#define INSN_LABEL2(insn, name) INSN_LABEL_ ## insn ## _ ## name
195#define INSN_LABEL(x) INSN_LABEL2(NAME_OF_CURRENT_INSN, x)
196
197#endif /* RUBY_VM_EXEC_H */
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40