[ruby/irb] Change debug test workaround only enabled when output is
[ruby.git] / vm_exec.c
blob44d92e2225c0e98e201e2b07fa83c76d32650038
1 /* -*-c-*- */
2 /**********************************************************************
4 vm_exec.c -
6 $Author$
8 Copyright (C) 2004-2007 Koichi Sasada
10 **********************************************************************/
12 #include <math.h>
14 #if USE_YJIT || USE_RJIT
15 // The number of instructions executed on vm_exec_core. --yjit-stats uses this.
16 uint64_t rb_vm_insns_count = 0;
17 #endif
19 #if VM_COLLECT_USAGE_DETAILS
20 static void vm_analysis_insn(int insn);
21 #endif
23 #if VMDEBUG > 0
24 #define DECL_SC_REG(type, r, reg) register type reg_##r
26 #elif defined(__GNUC__) && defined(__x86_64__)
27 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
29 #elif defined(__GNUC__) && defined(__i386__)
30 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
32 #elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
33 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
35 #elif defined(__GNUC__) && defined(__aarch64__)
36 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
38 #else
39 #define DECL_SC_REG(type, r, reg) register type reg_##r
40 #endif
41 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
43 #if !OPT_CALL_THREADED_CODE
44 static VALUE
45 vm_exec_core(rb_execution_context_t *ec)
47 #if defined(__GNUC__) && defined(__i386__)
48 DECL_SC_REG(const VALUE *, pc, "di");
49 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
50 #define USE_MACHINE_REGS 1
52 #elif defined(__GNUC__) && defined(__x86_64__)
53 DECL_SC_REG(const VALUE *, pc, "14");
54 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
55 #define USE_MACHINE_REGS 1
57 #elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
58 DECL_SC_REG(const VALUE *, pc, "14");
59 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
60 #define USE_MACHINE_REGS 1
62 #elif defined(__GNUC__) && defined(__aarch64__)
63 DECL_SC_REG(const VALUE *, pc, "19");
64 DECL_SC_REG(rb_control_frame_t *, cfp, "20");
65 #define USE_MACHINE_REGS 1
67 #else
68 register rb_control_frame_t *reg_cfp;
69 const VALUE *reg_pc;
70 #define USE_MACHINE_REGS 0
72 #endif
74 #if USE_MACHINE_REGS
76 #undef RESTORE_REGS
77 #define RESTORE_REGS() \
78 { \
79 VM_REG_CFP = ec->cfp; \
80 reg_pc = reg_cfp->pc; \
83 #undef VM_REG_PC
84 #define VM_REG_PC reg_pc
85 #undef GET_PC
86 #define GET_PC() (reg_pc)
87 #undef SET_PC
88 #define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
89 #endif
91 #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
92 #include "vmtc.inc"
93 if (UNLIKELY(ec == 0)) {
94 return (VALUE)insns_address_table;
96 #endif
97 reg_cfp = ec->cfp;
98 reg_pc = reg_cfp->pc;
100 first:
101 INSN_DISPATCH();
102 /*****************/
103 #include "vm.inc"
104 /*****************/
105 END_INSNS_DISPATCH();
107 /* unreachable */
108 rb_bug("vm_eval: unreachable");
109 goto first;
112 const void **
113 rb_vm_get_insns_address_table(void)
115 return (const void **)vm_exec_core(0);
118 #else /* OPT_CALL_THREADED_CODE */
120 #include "vm.inc"
121 #include "vmtc.inc"
123 const void **
124 rb_vm_get_insns_address_table(void)
126 return (const void **)insns_address_table;
129 static VALUE
130 vm_exec_core(rb_execution_context_t *ec)
132 register rb_control_frame_t *reg_cfp = ec->cfp;
133 rb_thread_t *th;
135 while (1) {
136 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
138 if (UNLIKELY(reg_cfp == 0)) {
139 break;
143 if (!UNDEF_P((th = rb_ec_thread_ptr(ec))->retval)) {
144 VALUE ret = th->retval;
145 th->retval = Qundef;
146 return ret;
148 else {
149 VALUE err = ec->errinfo;
150 ec->errinfo = Qnil;
151 return err;
154 #endif