Coverage Report

Created: 2026-06-03 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ruby/vm_exec.c
Line
Count
Source
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 USE_YJIT || USE_ZJIT
15
// The number of instructions executed on vm_exec_core. --yjit-stats and --zjit-stats use this.
16
uint64_t rb_vm_insn_count = 0;
17
#endif
18
19
#if VM_COLLECT_USAGE_DETAILS
20
static void vm_analysis_insn(int insn);
21
#endif
22
23
#if VMDEBUG > 0
24
#define DECL_SC_REG(type, r, reg) register type reg_##r
25
26
#elif defined(__GNUC__) && defined(__x86_64__)
27
36
#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
28
29
#elif defined(__GNUC__) && defined(__i386__)
30
#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
31
32
#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__))
33
#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
34
35
#elif defined(__GNUC__) && defined(__aarch64__)
36
#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
37
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 */
42
43
#if !OPT_CALL_THREADED_CODE
44
static VALUE
45
vm_exec_core(rb_execution_context_t *ec)
46
18
{
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
51
52
#elif defined(__GNUC__) && defined(__x86_64__)
53
18
    DECL_SC_REG(const VALUE *, pc, "14");
54
18
    DECL_SC_REG(rb_control_frame_t *, cfp, "15");
55
18
#define USE_MACHINE_REGS 1
56
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
61
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
66
67
#else
68
    register rb_control_frame_t *reg_cfp;
69
    const VALUE *reg_pc;
70
#define USE_MACHINE_REGS 0
71
72
#endif
73
74
18
#if USE_MACHINE_REGS
75
76
18
#undef  RESTORE_REGS
77
18
#define RESTORE_REGS() \
78
0
{ \
79
0
  VM_REG_CFP = ec->cfp; \
80
0
  reg_pc  = reg_cfp->pc; \
81
0
}
82
83
18
#undef  VM_REG_PC
84
18
#define VM_REG_PC reg_pc
85
18
#undef  GET_PC
86
18
#define GET_PC() (reg_pc)
87
18
#undef  SET_PC
88
18
#define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
89
18
#endif
90
91
18
#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
92
18
#include "vmtc.inc"
93
18
    if (UNLIKELY(ec == 0)) {
94
18
        return (VALUE)insns_address_table;
95
18
    }
96
0
#endif
97
0
    reg_cfp = ec->cfp;
98
0
    reg_pc = reg_cfp->pc;
99
100
0
  first:
101
0
    INSN_DISPATCH();
102
/*****************/
103
0
 #include "vm.inc"
104
/*****************/
105
0
    END_INSNS_DISPATCH();
106
107
    /* unreachable */
108
0
    rb_bug("vm_eval: unreachable");
109
0
    goto first;
110
0
}
111
112
const void **
113
rb_vm_get_insns_address_table(void)
114
18
{
115
18
    return (const void **)vm_exec_core(0);
116
18
}
117
118
#else /* OPT_CALL_THREADED_CODE */
119
120
#include "vm.inc"
121
#include "vmtc.inc"
122
123
const void **
124
rb_vm_get_insns_address_table(void)
125
{
126
    return (const void **)insns_address_table;
127
}
128
129
static VALUE
130
vm_exec_core(rb_execution_context_t *ec)
131
{
132
    register rb_control_frame_t *reg_cfp = ec->cfp;
133
    rb_thread_t *th;
134
135
    while (1) {
136
        reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp);
137
138
        if (UNLIKELY(reg_cfp == 0)) {
139
            break;
140
        }
141
    }
142
143
    if (!UNDEF_P((th = rb_ec_thread_ptr(ec))->retval)) {
144
        VALUE ret = th->retval;
145
        th->retval = Qundef;
146
        return ret;
147
    }
148
    else {
149
        VALUE err = ec->errinfo;
150
        ec->errinfo = Qnil;
151
        return err;
152
    }
153
}
154
#endif