Ruby: vm_exec.h Source File

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

vm_exec.h
Go to the documentation of this file.
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
14 typedef long OFFSET;
15 typedef unsigned long lindex_t;
16 typedef VALUE GENTRY;
17 typedef 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)printf
41/* #define throwdebug printf */
42
43#ifndef USE_INSNS_COUNTER
44#define USE_INSNS_COUNTER 0
45#endif
46
47/************************************************/
48#if defined(DISPATCH_XXX)
49 error !
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) fprintf(stderr, "exec: %s@(%"PRIdPTRDIFF", %"PRIdPTRDIFF")@%s:%u\n", #insn, \
78 (reg_pc - reg_cfp->iseq->body->iseq_encoded), \
79 (reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded), \
80 RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \
81 rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded)); \
82 if (USE_INSNS_COUNTER) vm_insns_counter_count_insn(BIN(insn));
83
84#define INSN_DISPATCH_SIG(insn)
85
86#define INSN_ENTRY(insn) \
87 LABEL(insn): \
88 INSN_ENTRY_SIG(insn); \
89
90/**********************************/
91#if OPT_DIRECT_THREADED_CODE
92
93/* for GCC 3.4.x */
94#define TC_DISPATCH(insn) \
95 INSN_DISPATCH_SIG(insn); \
96 RB_GNUC_EXTENSION_BLOCK(goto *(void const *)GET_CURRENT_INSN()); \
97 ;
98
99#else
100/* token threaded code */
101
102/* dispatcher */
103#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && __GNUC__ == 3
104#define DISPATCH_ARCH_DEPEND_WAY(addr) \
105 __asm__ __volatile__("jmp *%0;\t# -- inserted by vm.h\t[length = 2]" : : "r" (addr))
106
107#else
108#define DISPATCH_ARCH_DEPEND_WAY(addr) \
109 /* do nothing */
110#endif
111#define TC_DISPATCH(insn) \
112 DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
113 INSN_DISPATCH_SIG(insn); \
114 RB_GNUC_EXTENSION_BLOCK(goto *insns_address_table[GET_CURRENT_INSN()]); \
115 rb_bug("tc error");
116
117#endif /* OPT_DIRECT_THREADED_CODE */
118
119#define END_INSN(insn) \
120 DEBUG_END_INSN(); \
121 TC_DISPATCH(insn);
122
123#define INSN_DISPATCH() \
124 TC_DISPATCH(__START__) \
125 {
126
127#define END_INSNS_DISPATCH() \
128 rb_bug("unknown insn: %"PRIdVALUE, GET_CURRENT_INSN()); \
129 } /* end of while loop */ \
130
131#define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
132
133#define START_OF_ORIGINAL_INSN(x) start_of_##x:
134#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
135
136/************************************************/
137#else /* no threaded code */
138/* most common method */
139
140#define INSN_ENTRY(insn) \
141case BIN(insn):
142
143#define END_INSN(insn) \
144 DEBUG_END_INSN(); \
145 break;
146
147#define INSN_DISPATCH() \
148 while (1) { \
149 switch (GET_CURRENT_INSN()) {
150
151#define END_INSNS_DISPATCH() \
152default: \
153 SDR(); \
154 rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
155 } /* end of switch */ \
156 } /* end of while loop */ \
157
158#define NEXT_INSN() goto first
159
160#define START_OF_ORIGINAL_INSN(x) start_of_##x:
161#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
162
163#endif
164
165#define VM_SP_CNT(ec, sp) ((sp) - (ec)->vm_stack)
166
167#ifdef MJIT_HEADER
168#define THROW_EXCEPTION(exc) do { \
169 ec->errinfo = (VALUE)(exc); \
170 EC_JUMP_TAG(ec, ec->tag->state); \
171} while (0)
172#else
173#if OPT_CALL_THREADED_CODE
174#define THROW_EXCEPTION(exc) do { \
175 ec->errinfo = (VALUE)(exc); \
176 return 0; \
177} while (0)
178#else
179#define THROW_EXCEPTION(exc) return (VALUE)(exc)
180#endif
181#endif
182
183#define SCREG(r) (reg_##r)
184
185#define VM_DEBUG_STACKOVERFLOW 0
186
187#if VM_DEBUG_STACKOVERFLOW
188#define CHECK_VM_STACK_OVERFLOW_FOR_INSN CHECK_VM_STACK_OVERFLOW
189#else
190#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
191#endif
192
193#define INSN_LABEL2(insn, name) INSN_LABEL_ ## insn ## _ ## name
194#define INSN_LABEL(x) INSN_LABEL2(NAME_OF_CURRENT_INSN, x)
195
196#endif /* RUBY_VM_EXEC_H */
rb_iseq_struct
Definition: vm_core.h:444
error
void error(const char *msg)
Definition: untgz.c:593
VALUE
unsigned long VALUE
Definition: value.h:38
lindex_t
unsigned long lindex_t
Definition: vm_exec.h:15
OFFSET
long OFFSET
Definition: vm_exec.h:14
GENTRY
VALUE GENTRY
Definition: vm_exec.h:16
ISEQ
rb_iseq_t * ISEQ
Definition: vm_exec.h:17